Nokogiri を使って Evernote の XML (ENML) を tDiary の Wiki スタイルへ変換する
2011-05-12
Evernote のクライアントで tDiary の日記を書くために。 Evernote で作ったノートは、 ENML という XHTML のような XML 形式になっている。 これを tDiary の日記形式(Wikiスタイル)へ変換した。 ENML 形式のサンプルは EvernoteのAPI Overviewに書かれている。
ためしにPCのEvernoteクライアントで日記の下書きをしたところ、以下のようなデータになった。 <li>の部分はEvernoteクライアントの箇条書きを使ったところになる。 基本的にXHTMLライクな書式。
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">
<en-note style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">
テスト
<div><br/></div>
<div>* 箇条書き1-1</div>
<div>* 箇条書き1-2</div>
<div>* 箇条書き1-3</div>
<div><br/></div>
<ul>
<li>箇条書き2-1</li>
<li>箇条書き2-2</li>
</ul>
<div>段落</div>
一方、AndroidのEvernoteクライアントだとこうなる。 文字化けじゃないよ。
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd"><en-note style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div>これはテスト日記です。<br/>改行テスト。<br/>* 箇条書き1<br/>* 箇条書き2<br/>段落続き。<br/><br/>新規段落。<br/><br/> pre<br/><br/>段落。<br/> pre<br/>段落。<br/><br/>* 箇条書き1<br/>* 箇条書き2<br/><br/>! セクション<br/><br/>テスト。</div></en-note>
こちらは1つのdiv要素の中に本文が丸ごと入っている。 テキスト(本文)は実体参照になり、改行は<br/>を使ってる。
このフォーマットをWikiスタイルに変換する。 以前なら REXML を使うんだけど、いまなら Nokigiri がよさそう。 頭から順番に変換していけばいいので、DOMよりSAX向き。
Module Nokogiri::XML::SAXを読んで、以下のようなスクリプトを作った。
# wiki_style_document.rb - WikiStyle document format for ENML
#
class WikiStyleDocument < Nokogiri::XML::SAX::Document
attr_reader :text
def start_document
@text = ''
end
def start_element(name, attrs = [])
case name
when 'li'
@text << '* '
when 'br'
@text << "\n"
end
end
def characters(string)
@text << string
end
def to_s
@text
end
end
以下のようにして変換できる。
parser = Nokogiri::XML::SAX::Parser.new(doc = WikiStyleDocument.new)
parser.parse(xml)
puts doc.text
=> これはテスト日記です。
改行テスト。
* 箇条書き1
* 箇条書き2
段落続き。
新規段落。
pre
段落。
pre
段落。
* 箇条書き1
* 箇条書き2
<br/>タグなら改行、<li>なら「* 」に変換する。 それ以外はそのまま。 最初は<div>を改行に変換しなければいけないと思ってたけど、元のENMLに改行が含まれているので、これで上手く行った。
SAXって初めて使うけど、以外と簡単だね。