#:g1: chtml-matcherの紹介

Posted 2014-04-21 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の112日目です。

chtml-matcherとはなにか

 chtml-matcherは、Ian Eslick氏作のHTML(LHTML)に対してのパタンマッチのライブラリです。

パッケージ情報

パッケージ名chtml-matcher
Quicklisp
プロジェクトサイトeslick/chtml-matcher · GitHub
Quickdocshttp://quickdocs.org/chtml-matcher

インストール方法

(ql:quickload :chtml-matcher)

でインストールできますが、

; in: DEFUN SET-BINDING
;     (STDUTILS:ASSOC-SETF (CHTML-MATCHER::BINDINGS CHTML-MATCHER::DICT) (CHTML-MATCHER::CLEAN-VAR CHTML-MATCHER::VAR) CHTML-MATCHER::VALUE)
; --> LET* ASSOC 
; ==>
;   #<FUNCTION EQ>
; 
; caught ERROR:
;   Objects of type FUNCTION can't be dumped into fasl files.

のようなエラーになる場合、

(defmacro-exported assoc-setf (place key value &optional (test 'eq)) ...

のようにtest #'eqを 'eqに直しましょう。〈マクロ展開時に評価してしまうため、関数オブジェクトをfaslに書き出すことになってしまうのが原因〉

試してみる

 どんな関数があるかは、Quickdocsで確認できます。

 非常に大まかな説明のみで具体的な利用方法の解説がないのですが、解説によれば、"<"から始まるシンボルは、XPATHでいう//に相当するとのこと。
さらに、

のマッチのさせ方があります

 とりあえず、説明なしに簡単に使えそうなものから順に紹介します。

(defvar *html*
  (chtml-matcher:html->lhtml "<html><head></head><body><ul>
<li>a</li>
<li>b</li>
<li>c</li>
<li>d</li>
<li>e</li>
</ul></body></html>"))

find-in-lhtml

(chtml-matcher:find-in-lhtml *html* :ul nil)
;=>  (:UL NIL (:LI NIL "a") (:LI NIL "b") (:LI NIL "c") (:LI NIL "d") (:LI NIL "e"))

指定したノード以下を拾ってきます。

match-templateとget-bindings

(chtml-matcher:get-bindings 
 (chtml-matcher:match-template '(<ul () 
                                 (all ?elts
                                  (li () ?x)))
                               *html*))
;=>  ((:ELTS #<DICT 1 X> #<DICT 1 X> #<DICT 1 X> #<DICT 1 X> #<DICT 1 X>))

 match-templateでテンプレートとマッチさせ、get-bindingsでマッチしたものを取り出せます。
この例では、allでul以下の要素をまとめてeltsにマッチさせ、liの要素はxにマッチしています。

with-bindings

(chtml-matcher:with-bindings (elts)
                             (chtml-matcher:match-template '(<ul () 
                                                             (all ?elts
                                                              (li () ?x)))
                                                           *html*)
  (mapcan #'chtml-matcher:get-bindings elts))
;=>  ((:X . "a") (:X . "b") (:X . "c") (:X . "d") (:X . "e"))

 with-slots的にパタン変数と同名の束縛を作ります。

(chtml-matcher:with-bindings (a b c d)
                             (chtml-matcher:match-template 
                              '(<ul () 
                                (li () ?a)
                                (li () ?b)
                                (li () ?c)
                                (li () ?d))
                              *html*)
  (list a b c d))
;=>  ("a" "b" "c" "d")

まとめ

 今回は、chtml-matcherを紹介してみました。
あまりにもドキュメントがないので使い方は上記の説明で正しいのかさっぱりです。
説明がなくてもテストケースがあれば、なんとなく使い方も想像が付いたりもするのですが、テストケースもなく…。

comments powered by Disqus