2013年4月9日火曜日

emacsでXMLパースをやってみた

1. インストール
cd ~/.emacs.d/site-lisp/xml
wget http://repo.or.cz/w/emacs.git/blob_plain/HEAD:/lisp/xml.el
.emacsに以下を追記
(load-file "~/.emacs.d/site-lisp/xml/xml.el")
emacsを再起動します

2. サンプルXML作成
<post time="20050716234509" id="010101">
  <login>Test</login>
  <msg>Here is the message</msg>
  <info>MyUA</info>
</post>

上記をcd ~/.emacs.d/site-lisp/xml/sample.xmlとして保存してください
※他にも「XML サンプル」でググるとたくさんでてきます

3. 実行
scratchで以下のソースコードを記載

(let*
  ((xml (xml-parse-file
    (expand-file-name "~/.emacs.d/site-lisp/xml/sample.xml")))
    (post (car xml))
    (attrs (xml-node-attributes post))
    (time (cdr (assq 'time attrs)))
    (msg (car (xml-get-children post 'msg)))
    (text (car (xml-node-children msg))))
    (message "time: %s, message '%s'" time text))

eva-bufferもしくはカーソルを一番下にもっていきCtrl+jで実行できます
ミニバッファに
「time: 20050716234509, message 'Here is the message'」と出れば成功です
xmlをパースしたリストを返すようなメソッドを作成して受け取ったリストから
パースする流れを作ったほうがいいかもしれません


ちなみに文字列を直接パースする場合には以下の方法となります
ファイルの読み込み時とは異なるのでご注意を

(let*
  ((xml "<post time=\"20050716234509\" id=\"010101\"><login>Test</login><msg>Here is the message</msg><info>MyUA</info></post>")
    (root (with-temp-buffer (insert xml) (xml-parse-region (point-min) (point-max))))
    (post (car root))
    (attrs (xml-node-attributes post))
    (time (cdr (assq 'time attrs)))
    (msg (car (xml-get-children post 'msg)))
    (text (car (xml-node-children msg))))
    (message "time: %s, message '%s'" time text))

処理の流れとしてはXMLデータをlispで扱えるリスト形式のデータに落とし込んだ後にcarでリストから値を取得するという流れになっています
パースする部分は直感的で使いやすいなーと感じました


参考サイト
http://www.emacswiki.org/emacs/XmlParserExamples

0 件のコメント:

コメントを投稿