おかし日記(3月10日(土))経由で見つけたXPath 1.0を解説しているXMLマスター基礎講座 (XPath編)には誤りが沢山あります。というお話。
ノードを特定するための規格
まずここからして私の認識とは少し違います。XPath 1.0は:
これらを表現するための規格です。ノード集合を表現する方法の一つに「ロケーションパス」がありますが、このXMLマスター基礎講座 (XPath編) で取り上げられているのは「省略文法のロケーションパス」と「一部の関数」です。
'あ'
。これも「あ」という文字列を表すXPathの表現です。
とはいえロケーションパスはXPath 1.0の主要な部分であると言われていますから、揚げ足を取ったに過ぎません。もちろん非常に重要だと思うから書いたわけですが。例えばXSLTのvalue-of要素のselect属性には、XPathで文字列を表現したものを記述します。そうでないものは勝手に文字列に変換されているに過ぎません。
基本的には「.」「..」「/」「*」と要素名の組み合わせですね。
これまた私の認識とは違います。ロケーションパスの基本は:
/
」
/
」
以上の三つの組み合わせで、さらにロケーションステップは:
の三つで構成されている、と考えるのが基本かと思います。最小単位は「軸とノードテストのみから成る単一のロケーションステップ)」です。また、ノードテストは「要素名」ではないです。*等のキーワードか、あるいはQNameです。
と、ここまではジャブ。基本をおろそかにして省略文法を「基本」だと考えているとXPathには色々と罠があります。
//data[2][memo]
というロケーションパスについて、次のように解説されています。
文書内の2番目のdata要素を選択する。
ただし該当するdata要素が子要素memoを含まない場合、選択されない。
ダウト。
ルートノードの子孫ノード全てについて、その子供であるdata要素の内、二番目のものに絞込み、その中からmemo要素を子供に持っているものに絞り込みます。文書順(document order)で二番目とは限りません。因みに私なら/descendant::data[position() = 2][boolean(child::memo) = true()]
というパスで解説します。
last() 最後のノードを返す。
これも間違っています。
まず、XPathのビルトイン関数の中にノードを返却するものはありません。扱えるデータ型は前述の4つ。また、last()関数が返却するのは数値で、コンテクストサイズと呼ばれるものです。
述語を使うなら、XPathの基礎となっているコンテクストと、その言わばコンポーネントであるコンテクストサイズ、コンテクストポジション、コンテクストノード、関連付けられた名前空間くらいは、少なくとも意識している必要があると思います。
演算子を使用する際には注意する点がいくつかあります。 まず比較演算子のうち「<」「>」の文字は、「<」「>」と記述しなければなりません。
必ずしもそうする必要はありません。
not()を使う場合、()内に条件式を記述します。
not関数の引数はブール値です。条件式
?はそのブール値を表現するXPath 表現の一つに過ぎません。
ともかくXPathは色々な場面で使用する基礎的なものですから、きちんと仕様書を読むのが一番です。XPathには理念やら解釈なども存在しないので、やはり、仕様書を読むのが一番です。というか、解説を書くなら仕様書を参照すべきです(SHOULD)。2003-03-10現在、HTML文書としてぶっ壊れていますが、XMLパス言語 (XPath) Version 1.0という日本語訳もあるようです。
XMLマスター基礎講座(お世話になった書籍&ページ)には仕様書が見当たらず例の@ITが挙げられていますが、私はあそこの記事に突っ込みのメールを送ったことがあります。「/」をルート要素と説明していたからです(修正され済み)。日本の企業サイトが解説しているものには色々と違和感のある記事が多いので、突っ込みを連載企画にしようと思った程ですが、面倒なので止めました。営利系がどうなろうと知ったことではないのですよね。