0

XPath式のリストがあります。.NETで、リスト内のXPath式がアドレス指定されたスコープで重複していないことをテストする便利な方法はありますか?例:

string1 = /nodeA/nodeB/nodeC  
string2 = /nodeA/modeB/nodeD  

falseオーバーラップがないため生成されます。

string1 = /nodeA/nodeB/nodeC  
string2 = /nodeA/nodeB/nodeC/nodeF  

この引数のペアの場合true、式によって選択された要素のセットがstring1評価の結果とオーバーラップするため、返されstring2ます。

編集:
以下の回答から、「交差」ソリューションが利用可能であることがわかりましたが、XMLドキュメントに式を適用せずに重複する「競合」を解決する必要があるため、使用できません。私は今、恣意的なケースがほぼ不可能であることを理解しています。したがって、私の解決策は、許可される式のタイプを制限し、文字列比較を行うことです。

4

4 に答える 4

1

XSLT 2.0 および関連する仕様の正誤表を作成するために使用されるスタイルシートについて、これと同様の目的でコードを書いたことがあります。あなたはそれがあなたにいくつかのアイデアを与えることに気付くかもしれません。これには、複数の正誤表によって「影響を受ける」仕様内のテキストがないことを確認するロジックが含まれています。コードは次のとおりです (正誤表を定義する XML ドキュメントには、ベース ドキュメントのどのセクションが「影響を受ける」かを示す XPath 式が含まれているため、saxon:evaluate を使用します)。

ここでの主な目的は、2 つの XPath 式がオーバーラップするノードを選択するかどうかを判断することではなく、N 個のそのような式にオーバーラップがあるかどうかを判断することです。ここで、式は事前に知られていません。式のすべてのペア間のオーバーラップを探すことなく、これを実行したいと考えています。

count($x) != count($x/.) という興味深い表現があります。ここで ($x/.) は、ノード シーケンスから重複ノードを強制的に削除するために使用されます。したがって、テストでは、重複を削除するとノードが削除されるかどうか、つまり $x に重複が含まれるかどうかを尋ねます。

<!-- The following template checks that there is no element in the source document
     that is replaced or deleted by more than one erratum -->

<xsl:template name="check-for-conflicts">
  <xsl:variable name="directly-affected-elements" 
      select="er:eval-all(/er:errata/er:erratum[not(@superseded)]//er:old-text[not(starts-with(@action, 'insert-'))])"/>
  <xsl:variable name="all-affected-elements"
      select="for $e in $directly-affected-elements return $e/descendant-or-self::*"/>
  <xsl:if test="count($all-affected-elements) != count($all-affected-elements/.)">
     <!-- we now know there are duplicates, we just need to identify them... -->
     <xsl:for-each-group select="$all-affected-elements" group-by="generate-id()">
       <xsl:if test="count(current-group()) gt 1">
         <xsl:variable name="id" select="(ancestor::*/@id)[last()]"/>
         <xsl:variable name="section" select="$spec/key('id',$id)"/>
         <xsl:variable name="section-number">
           <xsl:number select="$section" level="multiple" count="div1|div2|div3|div4"/>
         </xsl:variable>
         <xsl:variable name="loc" select="er:location($section, .)"/>
         <p style="color:red">
           <xsl:text>WARNING: In </xsl:text>
           <xsl:value-of select="$section-number, $section/head"/>
           <xsl:text> (</xsl:text>
           <xsl:value-of select="$loc"/>
           <xsl:text>) Element is affected by more than one change</xsl:text>
         </p>
       </xsl:if>
     </xsl:for-each-group>
   </xsl:if>           
</xsl:template>

<!-- Support function for the check-for-conflicts template.
     This function builds a list (retaining duplicates) of all elements
     in the source document directly affected by a replacement or deletion.
     "Directly affected" means that the element is explicitly selected for replacement
     or deletion; the descendants of this element are indirectly affected. -->       

<xsl:function name="er:eval-all" as="element()*">
  <xsl:param name="in" as="element(er:old-text)*"/>
  <xsl:for-each select="$in">
    <xsl:variable name="id" select="@ref"/>
    <xsl:variable name="section" select="$spec/key('id',$id)"/>
    <xsl:variable name="exp" select="@select"/>
    <xsl:variable name="nodes" select="$section/saxon:evaluate($exp)"/>
    <xsl:sequence select="$nodes"/>
  </xsl:for-each>
</xsl:function>
于 2013-01-24T23:40:12.450 に答える
0

考えられるすべての入力に対してオーバーラップを計算する実際の機会はありませんが、特定の入力に対しては簡単に計算できます。

指定された入力の重複

/nodeA/nodeB/nodeC//*[. = /nodeA/modeB/nodeD//*]

は、右側のクエリにも含まれている左側のクエリの結果セット内のすべてのノードを検索します。これはintersect、@Tom が XPath 1.0 に対して提案したものを模倣しています。空のセットが返された場合、この入力に対してクエリは重複しません。結果が存在する場合、それらは重複します。

任意の入力で重複を見つけるのが難しい理由

次のような2つのクエリを考えてください

  • //*[@id](「id」属性を持つ als ノードを返す)
  • //someNode<someNode/>(すべての要素を返す)

要素がある場合は<someNode id="..."/>重複しますが、そうでない場合は重複しません。任意の入力に対する任意の XPath 式についてこれを解決するのは非常に困難です。

于 2013-01-24T21:29:35.707 に答える
0

2 つの XPath 式には、次を使用します

not(Expr1[count(.|Expr2) = count(Expr2)])

これが式のすべてのペアで評価され、答えが常にtrue()である場合、2 つの式が同じノードを選択することはありません。

すべての式で選択されているノードがあるかどうかを調べる必要がある場合:

not((Expr1 | Expr2 ... | ExprN)
      [count(.|Expr1) = count(Expr1)
     and
       count(.|Expr2) = count(Expr2)
     .  .  .  .  .  .  .  .  .  .  .  .
     and
       count(.|ExprN) = count(ExprN)
      ]
    )

そのようなノードがtrue()ない場合です。

于 2013-01-24T22:50:19.580 に答える
0

intersectXPath 2.0 で導入された演算子を使用して、これらの式で選択されたセットの共通部分が空かどうかを確認できます。

/nodeA/nodeB/nodeC intersect /nodeA/nodeB/nodeC/nodeF

私の知る限り、Saxonは XPath 2.0 をサポートしており、.NET プラットフォームで利用できます。この SO questionへの回答で言及されているいくつかの代替手段があります。自分で周りを見て回る必要があります。私は実際には .NET の人間ではないので、プラットフォームの新機能に詳しくありません。

LINQ to XML に基づくソリューションを探すこともできます。このようなアプローチについては、この msdn スレッドで説明されています。OPの(Santosh Benjaminの)ブログの概要は次のとおりです

于 2013-01-24T21:12:10.863 に答える