XPath 2.0 には、1.0 と比較して、シーケンスで機能するいくつかの新しい関数と構文があります。一部のセットは、言語が 1.0 で (ノード セットを使用して) 既に実行できたことに実際には追加されませんが、より読みやすい方法で目的のロジックを簡単に表現できるようにします。これにより、プログラマーがコードを正しく理解し、そのままにしておく可能性が高くなります。例えば、
empty(s)
は と同等not(s)
ですが、シーケンスが空かどうかをテストする場合は、その意図がより明確になります。- 訂正: シーケンスの有効なブール値は、一般にそれよりも複雑です。例
empty((0))
!=not((0))
. これは、ブール値のコンテキストでもexists(s)
vs.に適用されます。s
ただし、s
whereempty(s)
が と同等のドメインがあるnot(s)
ため、これらのドメイン内でこの 2 つを同じ意味で使用できます。しかし、これは、 を使用するとempty()
、コードを理解しやすくする上で重要な違いを生む可能性があることを示しています。
- 訂正: シーケンスの有効なブール値は、一般にそれよりも複雑です。例
- 同様に、XPath 1.0 に既に存在していたもの (またはブール値のコンテキストのみ)
exists(s)
と同等ですが、ここでも意図がより明確になっています。boolean(s)
s
- 数量化された表現; たとえば、"
some $x in
expressionsatisfies
test " はexpression test($x)
と同等です(ただし、新しい構文はより柔軟であり、コンテキスト項目を参照する変数があるため、コンテキスト項目が失われることを心配する必要はありません)。boolean(
[
(.)])
- 同様に、"
every $x in
expressionsatisfies
test " はexpression test($x)
と同等ですが、より読みやすくなっています。not(
[not(
(.))])
これらの関数と構文は、人間の考え方に簡単にマッピングできる XPath を作成するという目標を達成するためだけに、少なからずコストをかけて追加されたことは明らかです。これは、経験豊富な開発者が知っているように、理解しにくいコードよりも理解しやすいコードの方がはるかに優れていることを意味します。
以上のことを踏まえると、次のことを尋ねる XPath テスト式を作成する明確で読みやすい方法は何でしょうか。
値 X はシーケンス S で発生しますか?
いくつかの方法: (注:ここでは、値とシーケンスを示すためにX
andS
表記を使用しましたが、これらの部分式が要素名のテストであることや、単純な式であることを意味するものではありません。複雑になる可能性があります。 )
X = S
: これは最も読みにくいものの 1 つです。- X と S のどちらがシーケンスと単一の値であるかを考えてください
- 構文からは明らかでない一般的な比較を理解する
- ただし、この形式の利点の 1 つは、トピック(X) をコメント(「S のメンバーです」) の前に置くことができることです。これは、読みやすさに役立つと思います。
- 構文または名前が X および S の「カーディナリティ」を明らかにする場合、読みやすさに関するCMS の優れた点も参照してください。
index-of(S, X)
: これは、値として意図されているものとシーケンスとして意図されているものについて明確です ( への引数の順序を覚えている場合index-of()
)。しかし、それは私たちが必要とする以上のものを表現しています: 私たちが本当に知りたいのはX が S に現れるかどうかだけであるのに、インデックスを要求します。経験豊富な開発者は、多少の努力とコンテキストの理解により、意図されていることを理解します。しかし、各行の意図を理解するためにコンテキストに依存すればするほど、コードの理解が循環 (らせん) になり、場合によってはシーシュフェアンタスクになります! また、index-of()
X の出現のすべてのインデックスのリストを返すように設計されているため、必要以上にコストがかかる可能性があります。X = S
、必ずしも S のすべての内容を見つける必要も、順番に列挙する必要もありません。しかし、 のindex-of(S, X)
場合、正しい順序を決定する必要があり、S のすべての内容を X と比較する必要がありindex-of()
ますeq
。たとえば、ノードが特定のシーケンス内の ノードと同一であるかどうかを尋ねるために使用することはできません。- 修正:条件付きテストとして使用されるこのフォームは、実行時エラーになる可能性があります:
Effective boolean value is not defined for a sequence of two or more items starting with a numeric value
。(しかし、ゼロを返すことができないため、少なくとも間違ったブール値を取得することはありませindex-of()
ん。) S が X の複数のインスタンスを持つことができる場合、これはフォーム 3 または 6 を好むもう 1 つの正当な理由です。
- 修正:条件付きテストとして使用されるこのフォームは、実行時エラーになる可能性があります:
exists(index-of(X, S))
: 意図をより明確にし、プロセッサが十分にスマートであれば、プロセッサがパフォーマンスの低下を解消するのに役立ちます。some $m in S satisfies $m eq X
: これは非常に明確で、私たちの意図と完全に一致しています。1 に比べて長ったらしく、それ自体が可読性を低下させる可能性があります。しかし、それは明確にするために許容できる価格かもしれません。X と S は、それ自体が複雑な式になる可能性があることに注意してください。これらは、必ずしも単なる変数参照ではありません。利点は、演算子が明示的であるため、または他の比較演算子eq
に置き換えることができることです。is
S[. eq X]
: 1 よりも明確ですが、2 のセマンティックな欠点を共有しています: X と等しい S のすべてのメンバーを計算します。たとえば、 で発生した(0, 1)[. eq 0]
としても、偽の 0 を返します。0
(0, 1)
exists(S[. eq X])
: 1、2、3、5 よりクリア。4 ほどクリアではありませんが、短いです。5の欠点を回避します(または、プロセッサのスマートに応じて、少なくともそれらのほとんど)。
この時点で、私は最後のものに傾いています。exists(S[. eq X])
あなたはどうですか... 開発者として、XPath 2.0 を使用する複雑でなじみのない XSLT や XQuery、またはその他のプログラムに取り組み、そのプログラムが何をしているのかを理解したいと考えています。どのプログラムが最も読みやすいと思いますか?
長い質問をお詫びします。ここまで読んでくれてありがとう。
編集:「値の比較」(一般的な比較とは対照的に) が意図されている場所を簡単に確認できるように、上記の説明を可能な限り変更=
しました。eq