11

次の単純な XML ドキュメントがあります。

<?xml version="1.0" encoding="UTF-8"?>
<cars>
    <car>
        <data attrib="Make">
            <text>Volvo</text>
        </data>
        <data attrib="Model">
            <text>855</text>
        </data>
    </car>
    <car>
        <data attrib="Make">
            <text>Volvo</text>
        </data>
        <data attrib="Model">
            <text>745</text>
        </data>
    </car>
    <car>
        <data attrib="Make">
            <text>Volvo</text>
        </data>
        <data attrib="Model">
            <text>V70R</text>
        </data>
    </car>
</cars>

そして、次の XPath:

/cars/car/data[(@attrib='Model') and (text='855')]

これにより、次の結果が返されます。

<data attrib="Model"><text>855</text></data>

XPath が<car>一致のブロック全体を返すようにします。

したがって、戻りデータは次のようになります。

<cars>
    <car>
        <data attrib="Make">
            <text>Volvo</text>
        </data>
        <data attrib="Model">
            <text>855</text>
        </data>
    </car>
</cars>

これを実現するには、上記の XPath 式をどのように変更すればよいでしょうか?

4

2 に答える 2

15

XPath は、あなたが上ったノードを返しますdatacar代わりに、述語を の後に配置しますcar

/cars/car[data/@attrib='Model' and data/text='855']

もしくはもう少し短い

/cars/car[data[@attrib='Model' and text='855']]

この XMLPlaygroundで実行できます。

目的の出力を生成するための XQuery:

<cars>
  {/cars/car[data[@attrib='Model' and text='855']]}
</cars>
于 2012-07-05T08:36:25.470 に答える
3

以下は、可能な限り最短の XSLT ソリューションの完全でおそらく 1 つです。

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

 <xsl:template match="/*">
     <cars>
       <xsl:copy-of select="car[data[@attrib='Model' and text='855']]"/>
   </cars>
 </xsl:template>
</xsl:stylesheet>

ただし、ウェルノウンアイデンティティ ルールを使用した次の変換は、記述が容易であり、最大の柔軟性、拡張性、および保守性を提供します。

   <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="node()|@*">
         <xsl:copy>
           <xsl:apply-templates select="node()|@*"/>
         </xsl:copy>
     </xsl:template>

     <xsl:template match="car[not(data[@attrib='Model' and text='855'])]"/>
    </xsl:stylesheet>

これら 2 つの変換のいずれかが提供された XML ドキュメントに適用されると、次のようになります。

<cars>
    <car>
        <data attrib="Make">
            <text>Volvo</text>
        </data>
        <data attrib="Model">
            <text>855</text>
        </data>
    </car>
    <car>
        <data attrib="Make">
            <text>Volvo</text>
        </data>
        <data attrib="Model">
            <text>745</text>
        </data>
    </car>
    <car>
        <data attrib="Make">
            <text>Volvo</text>
        </data>
        <data attrib="Model">
            <text>V70R</text>
        </data>
    </car>
</cars>

必要な正しい結果が生成されます。

<cars>
   <car>
      <data attrib="Make">
         <text>Volvo</text>
      </data>
      <data attrib="Model">
         <text>855</text>
      </data>
   </car>
</cars>

説明:

  1. 最初の変換は最上位の要素を生成し、必要な要素carsを選択して、carそれを の本体としてコピーするだけですcars

  2. 2 番目の変換は、最も基本的で強力な XSLT 設計パターンの 1 つに基づいており、同一性規則を使用してオーバーライドします。

  3. ID テンプレートは、(処理対象として選択された) 一致したすべてのノードを「そのまま」コピーします。

  4. アイデンティティ ルールをオーバーライドするテンプレートが 1 つあります。このテンプレートcarは、 ではないものすべてに一致しdata[@attrib='Model' and text='855']ます。テンプレートの本体は空であり、一致した要素が出力にコピーされることはありません。つまり、一致する要素が「削除された」carと言えます。car

于 2012-07-06T12:21:18.320 に答える