XPathにおけるノード集合とその他のオブジェクトとの比較

前回で挙げた、XPathで一方に空のノード集合がある時の比較式について、jintrickさんに解説頂きました(感謝)。

ここで私は、3 != foo(偽)にスポットを当ててみました。数値(3)とノード集合foo!= で比較するとき、そのノード集合fooに含まれるの各ノードにnumber関数を適用して、3 に等しくないものが一つでもあれば真になります。number(foo)と比較されるのではないのです(number(foo)なら非数値(NaN)なので、3 != number(foo)は真になりますし)。そしてこのノード集合fooは空ですから、中にノードなんてありません。等しくないものが見つからないわけです。なんだかややこし過ぎて笑ってしまいました。

なるほどそういうことか……。てことはやはりXPath仕様書の以下の部分が該当するわけですね。ちょっと長いですが3.4 ブールの項より引用。

比較するオブジェクトが両方ともノード集合の場合は、1番目のノード集合内のノードと2番目のノード集合内のノードの文字列値を比較して、結果が真になるようなノードが両方のノード集合内にある場合のみ、比較結果は真になる。 比較するオブジェクトの1つがノード集合でもう1つが数値の場合は、number 関数を使用してノードの文字列値を数値に変換したものと比較対象の数値を比較して、結果が真になるようなノードがノード集合内にある場合のみ、比較結果は真になる。 比較するオブジェクトの1つがノード集合でもう1つが文字列の場合は、ノードの文字列値と比較対象の文字列を比較して、結果が真になるようなノードがノード集合内にある場合のみ、比較結果は真になる。 比較するオブジェクトの1つがノード集合でもう1つがブール値の場合には、boolean 関数を使用してノード集合をブール値に変換したものと比較対象のブール値を比較し、その結果が真になる場合のみ、比較結果は真になる。

改めて読むと漸く理解できました。また別の例を挙げると、

<?xml version="1.0">
<document>
 <p>abc</p>
 <p>def</p>
</document>

という文書を想定した場合、以下の比較式は両方とも真を返します(p要素を集めたノード集合には、各ノードの文字列値が'abc'に等しいものも、等しくないもの('def')も存在するため)。

しかし string(/document/p) を想定した場合、string関数は文書順で最初のノードの文字列値を返す……つまり最初のp要素の文字列値である'abc'を返すので、以下のようになるわけです。

XPathの比較式で比較の対象にノード集合を置く場合は、この辺りの仕組みを理解しておかないと。

(2004年5月5日)

北村曉 kits@akatsukinishisu.net