2

XPath 1.0 を使用して次の xml から重複したシリアル番号を特定しようとしていXPathNavigatorます。

<?xml version="1.0" encoding="utf-16"?>
<Inventory xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Items>
        <Item>
            <SerialNumber>1111</SerialNumber>
        </Item>
        <Item>
            <SerialNumber>1112</SerialNumber>
        </Item>
        <Item>
            <SerialNumber>1112</SerialNumber>
        </Item>
    </Items>
</Inventory>

これを評価してやってみました

//Items/Item/SerialNumber

.Netのカスタム XSLT コンテキスト関数 (IXsltContextFunction この MSDN の例のように実装) の式ですが、Invoke 関数は一度に 1 つの結果を呼び出すため、重複を見つけるために他の結果を表示することはできません。

1) 単一の XPath 1.0 式を使用してこれを行う方法はありますか?

また

2) カスタム XSLT コンテキスト関数クラスの単一の Invoke 呼び出しに要素の配列を渡す方法はありますか? 私は VB.Net で作業していますが、誰でも共有できる C# の例に満足しています。

ありがとう、

ギャビン

編集

OR Mapper と Dimitre の回答に感謝します。OR Mapper は私が要求したことを実行したため、最初は OR Mapper の応答を受け入れました。それ以来、私はそれが明確な値のリストを提供するのが好きなので、Dimitreの答えを受け入れました。どちらの回答も非常に役に立ちます!

4

2 に答える 2

4

私は1)に答えるつもりなので、2)はもう問題にならないはずです:

preceding-sibling要素の軸を使用して、同じシリアル番号を持つ<Item>前の要素を見つけることができます。<Item>

これを試してください(要素ではなくシリアル番号自体のみを返すように書かれています-これがあなたが望むものではなく、結果を変更する方法がわからない場合は、私に知らせてください):

/Inventory/Items/Item/SerialNumber/node()[.=../../preceding-sibling::Item/SerialNumber/node()]

サンプル ドキュメントの場合は、次のように返されます。

1112
于 2012-06-26T08:07:56.087 に答える
3

使用:

/*/*/Item
      [SerialNumber = following-sibling::Item/SerialNumber
     and
       not(SerialNumber = preceding-sibling::Item/SerialNumber)
      ]

これにより、同じ文字列値を持つ子を持つ要素Itemのグループに対して、1 つの要素だけが選択されます。ItemSerialNumber

XSLT ベースの検証:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

 <xsl:template match="/">
     <xsl:copy-of select=
      "/*/*/Item
          [SerialNumber = following-sibling::Item/SerialNumber
         and
           not(SerialNumber = preceding-sibling::Item/SerialNumber)
          ]"/>
 </xsl:template>
</xsl:stylesheet>

この変換がこの XML ドキュメントに適用されると(提供されたものに基づいていますが、より興味深いものになっています):

<Inventory>
    <Items>
        <Item>
            <SerialNumber>1111</SerialNumber>
        </Item>
        <Item>
            <SerialNumber>2222</SerialNumber>
        </Item>
        <Item>
            <SerialNumber>2222</SerialNumber>
        </Item>
        <Item>
            <SerialNumber>2222</SerialNumber>
        </Item>
        <Item>
            <SerialNumber>1111</SerialNumber>
        </Item>
        <Item>
            <SerialNumber>1111</SerialNumber>
        </Item>
        <Item>
            <SerialNumber>3333</SerialNumber>
        </Item>
    </Items>
</Inventory>

変換は XPath 式を評価し、選択したノードを出力にコピーします。

<Item>
   <SerialNumber>1111</SerialNumber>
</Item>
<Item>
   <SerialNumber>2222</SerialNumber>
</Item>

SerialNumber最後に、重複した値だけを取得したい場合は、次を使用します。

   /*/*/Item
          [SerialNumber = following-sibling::Item/SerialNumber
         and
           not(SerialNumber = preceding-sibling::Item/SerialNumber)
          ]
           /SerialNumber/text()
于 2012-06-26T13:01:28.897 に答える