blog.yatsu.info: CocoaでTxを使うためのObjcラッパー tx-objc-wrapper で書いたtx-objc-wrapperにはもうひとつHatenaKeywordsというサンプルプログラムがあります。
これはiPhone用のシンプルなブラウザアプリで、開いたWebページのすべてのはてなキーワードをリンクに置換するものです。
このアプリをビルドするには、tx-objc-wrapperディレクトリで以下のようにはてなキーワードCSVをダウンロードします。
% wget http://d.hatena.ne.jp/images/keyword/keywordlist_furigana.csv
そして HatenaKeywords/HatenaKeywords.xcodeproj をXcodeでビルドします。
起動するとUIWebViewでWikipedia日本語版を読み込み、以下のようにキーワードを置換します。緑色がはてなキーワードへのリンクです。
iPhone 3G実機で26万語からTxを構築すると90秒くらいかかります。ラッパーのコードがNSStringへの変換などを含んでいて、その分遅いかもしれません。後でチューニングしようと思います。
2回目に起動すると、前回構築したTxを読み込みます。
以下が実装の主な部分です。
- (void)webViewDidFinishLoad:(UIWebView *)aWebView {
NSError *error = nil;
// get the original HTML
NSString *html = [aWebView stringByEvaluatingJavaScriptFromString:@"document.body.innerHTML;"];
DDXMLDocument *doc =
[[DDXMLDocument alloc] initWithHTMLString:html
options:HTML_PARSE_NOWARNING | HTML_PARSE_NOERROR
error:&error];
// find text nodes that are not included in a link
NSArray *nodes = [doc nodesForXPath:@"//*[name(.)!='a']/text()"
error:&error];
for (DDXMLNode *node in nodes) {
[node setStringValue:[txo replace:[node stringValue]]];
}
// generate HTML from DDXMLDocument
html = [[[NSString alloc] initWithData:[doc XMLData]
encoding:NSUTF8StringEncoding]
autorelease];
// replace '[[[word]]]' with 'word'
NSString *linkStr = [NSString stringWithFormat:@"$1"];
html = [html stringByReplacingOccurrencesOfRegex:@"\\[\\[\\[([^\\]]*)\\]\\]\\]"
withString:linkStr];
// escape quotation marks
html = [html stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"];
// make it one line
html = [html stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"];
// execute the JavaScript code
NSString *js = [NSString stringWithFormat:@"document.body.innerHTML = '%@';", html];
[aWebView stringByEvaluatingJavaScriptFromString:js];
}
このメソッドはUIWebViewの読み込みが終わったときに呼び出され、以下を行います。
- JavaScriptを実行しHTML(
document.body.innerHTML)を取得する - XPathでリンクの外のテキストノードを取得する
(KissXML+HTMLを使用) - [Txo replace:] ではてなキーワードを [[[キーワード]]] に置換し、ノードにセット
- DDXMLDocumentからHTMLを生成
- 正規表現で [[[キーワード]]] をリンクに置換
(RegexKitLiteを使用) - HTML文字列のクォーテーションマークをエスケープ
- HTML文字列を1行にまとめる
- JavaScriptでUIWebViewのHTMLを置き換える





