1. ホーム
  2. xslt

[解決済み] XSLTで指定された値を持つ要素を数える

2022-02-08 03:38:53

質問

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

EDIT: 私は元の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レベルのプロパティのうち、テンプレートパラメータで定義された長い値(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要素を定義することが可能です。しかし、quot;ID"の下にあるProperty要素("Value")は1つだけで、"Value"の下にある要素は1つだけだと考えて間違いないでしょう。

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

解決するには?

この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やValue)をすべて削除したことに注意してください。XMLの階層構造から関連するノードに到達することができるため、これらは必要ないように思われます。また、一意性のチェックが long 要素を使用します。