TclDOM

 千葉県の勝浦に遊びに行くと、 私はいつも勝浦駅前のドムドムでセットを食べながら地図を確認しつつ、 旅ルートの確認をします。 今日はその縁もあって、ドムドムの話を少ししたいと思います。




   (違うやろ)




 TclDOMは、Tclスクリプトで使えるDOM(Document Object Model)パーサです。 DOMについて詳しくは省略します。 XML関係の書籍などの情報をチェックして下さい。 TclDOMには前のページでも少しだけ紹介しましたが、 純粋Tclで書かれたDOMパーサの他に、 The XML C Library for GNOME(libxml2) のパーサの2種類があります。 Windows用のバイナリパッケージ、ActiveTclには後者のライブラリも同梱されており、 すぐに使えるようになっているので、これを使うことにします。 環境は WindowsXP Home Edition、ActiveTcl 8.4.3.0(TclDOM 2.6)です。

●サンプル
このサンプルは、単にXML文書を解析して、要素ノードを見つけたら要素名と、 その内容、属性があったらその名前と値を順番に表示していくという処理を行います。

package require dom::libxml2

set filename [lindex $argv 0]

set fin [open $filename r]
fconfigure $fin -encoding utf-8
set xmlstr [read $fin]; close $fin

proc checkNode node {
  set children [::dom::node cget $node -childNodes]
  set nodeName [::dom::node cget $node -nodeName]
  set nodeType [::dom::node cget $node -nodeType]
  set nodeValue [::dom::node cget $node -nodeValue]

  puts "$nodeType:$nodeName:$nodeValue"
  if {$nodeType == "element"} {
    set attrlist [array get [::dom::node cget $node -attributes]]
    if {[llength $attrlist] > 0} {
      puts "  ATTR $attrlist"
    }
  }
  foreach c [set $children] {
    # サイコします。
    checkNode $c
  }
}

set xmldoc [::dom::libxml2::parse $xmlstr]
set docele [::dom::libxml2::document cget $xmldoc -documentElement]
checkNode $docele
# end.

 ということで、上のほうから少しずつ紹介してまいります。
まず、解析対象のXML文書はTcl文字列として読み取ります。ここでいきなり注意ですが、 TclDOMのバイナリ配布に含まれるlibxml2では、 UTF-8以外のエンコーディングをサポートしていないようなので、 シフトJISなどで書かれたXML文書も、binaryモードで読まずに、 fconfigure -encoding cp932等として、Tclの内部ではUTF-8で持つようにして、 処理をさせます。つまり、シフトJISなどで書かれたXML文書も、 Tclの内部ではUTF-8になるので別に問題ないのですが、ここで別の問題が! XML文書の最初に <xml version="1.0" encoding="..." ?> という一文を普通入れますが、ここで encodingがShift_JISとかになっていると失敗します。 encoding=を削るか、あえて書くならUTF-8と書かないといけません。

 処理自体は一本道です。 ::dom::libxml2::parseコマンドでXML文書からDOMツリーを構築し、 ::dom::libxml2::document cget {domdom} -documentElement コマンドでルートノードの要素オブジェクト(のTcl名前空間での名前) を取り出して、それ以下のDOMツリーをサイコ的に走査していきます。 ノードの名前、タイプ(要素、テキスト、コメント、etc)、 値、属性値、それに自分の子ノードのリストはいずれもノードオブジェクトの属性を cgetすることで取得できます。 サンプルでも使っているように、それぞれ -nodeName、-nodeType、-nodeValue、-attributes、-childNodes で取得できます。 ここで-childNodesは子ノードのTclリストで、 -attributeは属性ノードの配列変数です。

 なお、::dom::libxml2 のところを ::dom::tcl にすれば、純粋Tclの処理系が代わりに作動するわけですが、 次のようなよく分からぬエラーとなり、解決できていません。

error "unclosed token" at line 885 character 103
    while executing
"$parser parse [lindex $args 0]"
error "unclosed token" at line 885 character 103
    while executing
"::dom::tcl::DOMImplementation parse {?<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="achaa.xsl" ?>

拡張レビュー分室 top
(first uploaded 2003/06/15 last updated 2003/06/15, MISUMI URANO)