23

特定の値を持つ XML ファイル内の要素の数を数える必要があります (一意性を確認するため)。XML ファイルは次のようになります。

編集:元の「簡略化された」XML を、誰かが設計した実際の毛むくじゃらの混乱で更新しました。残念ながら、これにより、編集しない限り、以前のすべての回答が本当に混乱し、間違ったものになります。

<root>
  <ac>
   <Properties>
     <Property Name="Alive">
      <Properties>
        <Property Name="ID">
         <Properties>
           <Property Name="Value">
            <long>11007</long>
           </Property>
         </Properties>
        </Property>
      </Properties>
     </Property>
     <Property Name="Dead">
      <Properties>
        <Property Name="ID">
         <Properties>
           <Property Name="Value">
            <long>11008</long>
           </Property>
         </Properties>
        </Property>
      </Properties>
     </Property>
     ...
     <Property Name="MostlyDeadAllDay">
      <Properties>
        <Property Name="ID">
         <Properties>
           <Property Name="Value">
            <long>99001</long>
           </Property>
         </Properties>
        </Property>
      </Properties>
     </Property>
   </Properties>
  </ac>
</root>

変数を定義して、テンプレート パラメーターで定義された long 値 (ID) を持つ Alive/Dead レベルのプロパティの数を確認しようとしています。これらの線に沿った何か(これは間違っていると思いますが)...

<xsl:param name="parPropId"/>
<xsl:variable name="countProperties">
   <xsl:value-of select="count(/root/ac/
      Properties/Property/
      Properties/Property[@Name = 'ID']/
      Properites/Property[@Name = 'Value']/long = $parPropId)"/>
</xsl:variable>

「ID」レベルで複数の Property 要素を定義できます。しかし、「ID」の下の Property 要素 (「Value」) は 1 つだけであり、「Value」の下の「長い」要素は 1 つだけであると確信しています。

[免責事項] 私が立ち往生している XML ファイル全体を設計した人は、XML を構造化する方法を本当に知りませんでした (たとえば、属性と要素を逆に使用するなど)。結果として、私の XSLT の考え方が一時的に歪められているのではないかと心配しています :)。[/免責事項]

4

3 に答える 3

43

このXPath:

count(//Property[long = '11007'])

以下と同じ値を返します。

count(//Property/long[text() = '11007'])

...ただし、最初はProperty基準に一致するノードをカウントし、2 番目は基準にlong一致する子ノードをカウントします。

あなたのコメントとあなたの質問を数回読んだように、基準の組み合わせに基づいて独自性を見つけたいと思っていると思います。したがって、実際には複数の条件を実際にチェックしていると思います。以下も同様に機能します。

count(//Property[@Name = 'Alive'][long = '11007'])

以下と同じ意味だからです。

count(//Property[@Name = 'Alive' and long = '11007'])

もちろん、テンプレートのパラメーターの値を置き換えます。上記のコードは要点のみを示しています。

EDIT(質問編集後)


XML がひどいものであるというあなたの意見は正しかったです。実際、これは実にCodingHorrorの候補です! 現在使用している「Property」ノードを追跡するために、数え続けなければなりませんでした。あなたの痛みが分かります!

どうぞ:

count(/root/ac/Properties/Property[Properties/Property/Properties/Property/long = $parPropId])

他のすべてのチェック (ID と値) を削除したことに注意してください。XML の階層を使用して関連するノードに到達できるため、それらは必須ではないようです。longまた、一意性のチェックは要素の内容のみに基づいていると既に述べました。

于 2009-04-06T16:29:54.460 に答える
2

xpathが少しずれています:

count(//Property/long[text()=$parPropId])

編集:Cerebrusは、OP内のコード(ノードの暗黙の値を使用)が目的に完全に適していることを非常に正しく指摘しています。実際、「long」ノードではなく「Property」ノードを使用する可能性が非常に高いため、text()xpathよりも要求する方がおそらく優れて//Property[long=$parPropId]ますが、読みやすさの理由から後者の場合を説明することもできます。 。

何と言えば、今日は少し疲れています:)

于 2009-04-06T15:30:12.983 に答える
-2
<xsl:variable name="count" select="count(/Property/long = $parPropId)"/>

テストされていませんが、うまくいくはずです。プロパティノードはルートノードの直接の子であると想定しているため、パフォーマンスのために子孫セレクターを取得します

于 2009-04-06T15:28:21.537 に答える