4

XPath 2.0 には、1.0 と比較して、シーケンスで機能するいくつかの新しい関数と構文があります。一部のセットは、言語が 1.0 で (ノード セットを使用して) 既に実行できたことに実際には追加されませんが、より読みやすい方法で目的のロジックを簡単に表現できるようにします。これにより、プログラマーがコードを正しく理解し、そのままにしておく可能性が高くなります。例えば、

  • empty(s)は と同等not(s)ですが、シーケンスが空かどうかをテストする場合は、その意図がより明確になります。
    • 訂正: シーケンスの有効なブール値は、一般にそれよりも複雑です。例empty((0))!= not((0)). これは、ブール値のコンテキストでもexists(s)vs.に適用されます。sただし、swhereempty(s)が と同等のドメインがあるnot(s)ため、これらのドメイン内でこの 2 つを同じ意味で使用できます。しかし、これは、 を使用するとempty()、コードを理解しやすくする上で重要な違いを生む可能性があることを示しています。
  • 同様に、XPath 1.0 に既に存在していたもの (またはブール値のコンテキストのみ)exists(s)と同等ですが、ここでも意図がより明確になっています。boolean(s)s
  • 数量化された表現; たとえば、" some $x in expression satisfies test " はexpression test($x)と同等です(ただし、新しい構文はより柔軟であり、コンテキスト項目を参照する変数があるため、コンテキスト項目が失われることを心配する必要はありません)。boolean([(.)])
  • 同様に、" every $x in expression satisfies test " はexpression test($x)と同等ですが、より読みやすくなっています。not([not((.))])

これらの関数と構文は、人間の考え方に簡単にマッピングできる XPath を作成するという目標を達成するためだけに、少なからずコストをかけて追加されたことは明らかです。これは、経験豊富な開発者が知っているように、理解しにくいコードよりも理解しやすいコードの方がはるかに優れていることを意味します。

以上のことを踏まえると、次のことを尋ねる XPath テスト式を作成する明確で読みやすい方法は何でしょうか。

値 X はシーケンス S で発生しますか?

いくつかの方法: (注:ここでは、値とシーケンスを示すためにXandS表記を使用しましたが、これらの部分式が要素名のテストであることや、単純な式であることを意味するものではありません。複雑になる可能性があります。 )

  1. X = S: これは最も読みにくいものの 1 つです。
    • X と S のどちらがシーケンスと単一の値であるかを考えてください
    • 構文からは明らかでない一般的な比較を理解する
      1. ただし、この形式の利点の 1 つは、トピック(X) をコメント(「S のメンバーです」) の前に置くことができることです。これは、読みやすさに役立つと思います。
      2. 構文または名前が X および S の「カーディナリティ」を明らかにする場合、読みやすさに関するCMS の優れた点も参照してください。
  2. 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 つの正当な理由です。
  3. exists(index-of(X, S)): 意図をより明確にし、プロセッサが十分にスマートであれば、プロセッサがパフォーマンスの低下を解消するのに役立ちます。
  4. some $m in S satisfies $m eq X: これは非常に明確で、私たちの意図と完全に一致しています。1 に比べて長ったらしく、それ自体が可読性を低下させる可能性があります。しかし、それは明確にするために許容できる価格かもしれません。X と S は、それ自体が複雑な式になる可能性があることに注意してください。これらは、必ずしも単なる変数参照ではありません。利点は、演算子が明示的であるため、または他の比較演算子eqに置き換えることができることです。is
  5. S[. eq X]: 1 よりも明確ですが、2 のセマンティックな欠点を共有しています: X と等しい S のすべてのメンバーを計算します。たとえば、 で発生した(0, 1)[. eq 0]としても、偽の 0 を返します。0(0, 1)
  6. exists(S[. eq X]): 1、2、3、5 よりクリア。4 ほどクリアではありませんが、短いです。5の欠点を回避します(または、プロセッサのスマートに応じて、少なくともそれらのほとんど)。

この時点で、私は最後のものに傾いています。exists(S[. eq X])

あなたはどうですか... 開発者として、XPath 2.0 を使用する複雑でなじみのない XSLT や XQuery、またはその他のプログラムに取り組み、そのプログラムが何をしているのかを理解したいと考えています。どのプログラムが最も読みやすいと思いますか?

長い質問をお詫びします。ここまで読んでくれてありがとう。

編集:「値の比較」(一般的な比較とは対照的に) が意図されている場所を簡単に確認できるように、上記の説明を可能な限り変更=しました。eq

4

4 に答える 4

4

価値があるのは、名前またはコンテキストが X がシングルトンであることを明確にしている場合、最初の形式 X = S を喜んで使用します-たとえば、可能な値のセットに対して属性値をチェックしたい場合:

<xsl:when test="@type = ('A', 'A+', 'A-', 'B+')" />

また

<xsl:when test="@type = $magic-types"/>

混乱のリスクがあると思うなら、私はあなたの6番目の定式化が好きです. 有効なブール値を計算するためのルールを覚える頻度が減れば減るほど、ルールを間違える頻度も減ります。

于 2013-06-22T18:16:24.593 に答える
2

functxライブラリにはこの関数の優れた実装があるため、次を使用できます。

functx:is-node-in-sequence($X, $Y)

(この特定の関数はhttp://www.xqueryfunctions.com/xq/functx_is-node-in-sequence.htmlにあります)

functxライブラリ全体は、XQuery(http://www.xqueryfunctions.com/)とXSLT(http://www.xsltfunctions.com/)の両方で利用できます。

Marklogicは、functxライブラリをコア製品とともに出荷しています。他のベンダーもそうかもしれません。

于 2013-03-15T18:24:52.880 に答える
2

私はこれを好む

count(distinct-values($seq)) eq count(distinct-values(($x, $seq)))

$x 自体がシーケンスの場合、この式は、シーケンスとして表される2 つの値のセット間の関係の (値ベースの)サブセットを実装します。のサブセットのこの実装は、時間の複雑さが線形であるのに対し、O(N^2)) の時間の複雑さを持つ、これを表現する他の多くの方法とは対照的です。

要約すると、単一の値が値のセットに属するかどうかという問題は、ある値のセットが別の値のサブセットであるかどうかという問題の特殊なケースです。後者の適切な実装があれば、前者に答えるためにそれを使用できます。

于 2013-03-15T04:13:11.307 に答える
0

ノードX がシーケンス S で発生するかどうかを知りたい場合の別の可能性は、次のとおりです。

exists((X) intersect S)

かなり読みやすく、簡潔だと思います。ただし、X と S の値がノードの場合にのみ機能します。質問しようとしたら

exists(('bob') intersect ('alice', 'bob'))

実行時エラーが発生します。私が現在取り組んでいるプログラムでは、文字列を比較する必要があるため、これはオプションではありません。

Dimitri が指摘しているように、シーケンス内のノードの出現は、値の比較ではなく、同一性の問題です。

于 2013-03-15T21:09:55.580 に答える