■
- XPathにおけるノード集合とその他のオブジェクトとの比較 - 徒書
北村さんが引用している仕様書の箇所を読んだら、
true() != foo
(fooは空のノード集合)は真であると気づきました。この時は各ノードではなくてノード集合foo
自身にboolean
関数が適用されるようです(true() != false()
で真)。MSXML4.0は正しかった。4Suiteの実装が間違い。でも片方がブール値の時だけ処理が違うというのも一貫性が無くて混乱の元だし、Ogbujiさんを責める気にはなれません。私も勘違いしていたわけだし。一応原文もチェック:If one object to be compared is a node-set and the other is a boolean, then the comparison will be true if and only if the result of performing the comparison on the boolean and on the result of converting the node-set to a boolean using the boolean function is true.
3.4 Booleans(XML Path Language (XPath))より
ふと気づいて青い本(謎)を調べたら、やっぱり勘違いしていました。
- XSLTで、同じ属性値を持つ要素の範囲内で連番を振る - 徒書
-
ここで挙げられている問題について、分かりやすく説明する為に更に条件を絞り込んでみました。fooは空のノード集合です。
self::* != foo
foo != foo
3 != foo
'あ' != foo
以上、全部偽でした。つまり空のノード集合は、ブール値以外の何と比較しても必ず偽でした。
true() != foo
MSXMLでは、このようにブール値と比較したときには、予想通りの結果が得られます。真です。4Suiteライブラリを使用すると偽でした。
ここで私は、
3 != foo
(偽)にスポットを当ててみました。数値(3)とノード集合foo
を!=
で比較するとき、そのノード集合foo
に含まれるの各ノードにnumber
関数を適用して、3
に等しくないものが一つでもあれば真になります。number(foo)
と比較されるのではないのです(number(foo)
なら非数値(NaN)なので、3 != number(foo)
は真になりますし)。そしてこのノード集合foo
は空ですから、中にノードなんてありません。等しくないものが見つからないわけです。なんだかややこし過ぎて笑ってしまいました。'あ' != foo
も全く同じです。foo
というノード集合に含まれるノードの中に、'あ'
でない文字列が見つからないので、偽なのです。self::* != foo
にしても同様ですが少し複雑です。self::*
内の各ノードの文字列値それぞれと、foo
内の各ノードの文字列値それぞれとを比較して、一つでも異なるならばこれは真です。しかし、そもそもfoo
内にノードが無いので異なるものを見つけることが出来ず、よって偽になります。しかし、すると
true() != foo
は何故MSXMLで真になるのでしょうか。片方がブール値の場合は、各ノードではなくてノード集合自身にboolean関数が適用されるfoo
内の各ノードにboolean
関数を適用した結果、その中に、一つでもfalse()
がなければtrue() != foo
は真にならないはずです。実装の不具合でしょうか。更に、
foo = foo
やfoo != foo
では何が行われているのか私にはさっぱりわかりません。私は以前から書いていますが、XPathやXSLTでは、自分の意図する型に明示的に変換して、暗黙の型変換は可能な限り避けるべきだと思います。James Clarkあたり以外。