web-dev-qa-db-ja.com

特定の値を持つ要素をカウントするXSLT

特定の値を持つ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>

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

<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」の下にある1つのProperty要素(「Value」)と、「Value」の下にある1つの「long」要素のみに頼ることができると確信しています。

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

18
e-holder

この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 候補です!私が現在いた「プロパティ」ノードを追跡するために、再カウントを続けなければなりませんでした。あなたの痛みが分かります!

どうぞ:

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

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

39
Cerebrus

Xpathは少し外れています。

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

編集:Cerebrusは、OP内のコード(ノードの暗黙的な値を使用)が目的に対して絶対に適切であることを指摘しています。実際、「長い」ノードではなく「プロパティ」ノードを使用したい可能性が高いため、おそらくtext)xpathよりも//Property[long=$parPropId]を要求するのは---(superiorです。ただし、読みやすさの理由で後者を主張することもできます。

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

2
annakata