前回で挙げた、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')も存在するため)。
'abc' = /document/p
'abc' != /document/p
しかし string(/document/p)
を想定した場合、string関数は文書順で最初のノードの文字列値を返す……つまり最初のp要素の文字列値である'abc'を返すので、以下のようになるわけです。
'abc' = string(/document/p)
は、真を返す。'abc' != string(/document/p)
は、偽を返す。XPathの比較式で比較の対象にノード集合を置く場合は、この辺りの仕組みを理解しておかないと。
(2004年5月5日)
北村曉 kits@akatsukinishisu.net