at posts/single.html

Nokogiri を使って Evernote の XML (ENML) を tDiary の Wiki スタイルへ変換する

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>&#12371;&#12428;&#12399;&#12486;&#12473;&#12488;&#26085;&#35352;&#12391;&#12377;&#12290;<br/>&#25913;&#34892;&#12486;&#12473;&#12488;&#12290;<br/>* &#31623;&#26465;&#26360;&#12365;1<br/>* &#31623;&#26465;&#26360;&#12365;2<br/>&#27573;&#33853;&#32154;&#12365;&#12290;<br/><br/>&#26032;&#35215;&#27573;&#33853;&#12290;<br/><br/> pre<br/><br/>&#27573;&#33853;&#12290;<br/> pre<br/>&#27573;&#33853;&#12290;<br/><br/>* &#31623;&#26465;&#26360;&#12365;1<br/>* &#31623;&#26465;&#26360;&#12365;2<br/><br/>! &#12475;&#12463;&#12471;&#12519;&#12531;<br/><br/>&#12486;&#12473;&#12488;&#12290;</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って初めて使うけど、以外と簡単だね。

参考: SAXによるXML文書の操作 @IT

関連する日記