web-dev-qa-db-fra.com

Éléments de comptage XSLT avec une valeur donnée

J'ai besoin de compter le nombre d'éléments dans un fichier XML qui ont une valeur particulière (pour vérifier l'unicité). Le fichier XML ressemble à ceci:

EDIT: J'ai mis à jour le XML "simplifié" original avec le désordre velu réel que quelqu'un a conçu. Malheureusement, cela va rendre toutes les réponses précédentes vraiment déroutantes et erronées à moins qu'elles ne soient modifiées.

<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>

J'essaie de définir une variable pour voir combien de propriétés au niveau Alive/Dead ont la valeur longue (ID) telle que définie dans un paramètre de modèle. Quelque chose dans ce sens (même si je soupçonne que c'est faux) ...

<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>

Il peut y avoir plusieurs éléments de propriété définis au niveau "ID". Mais je suis assez certain de pouvoir compter sur un seul élément Property ("Value") sous "ID" et un seul élément "long" sous "Value".

[Clause de non-responsabilité] Celui qui a conçu le fichier XML global avec lequel je suis coincé à travailler VRAIMENT ne savait pas comment structurer XML (par exemple, l'utilisation à rebours des attributs par rapport aux éléments). Je crains que ma pensée XSLT ait été temporairement déformée :) en conséquence. [/avertissement]

18
e-holder

Ce XPath:

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

renvoie la même valeur que:

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

... sauf que le premier compte Property nœuds qui correspondent au critère et le second compte long nœuds enfants qui correspondent au critère.

Selon votre commentaire et la lecture de votre question à quelques reprises, je pense que vous voulez trouver l'unicité basée sur une combinaison de critères. Par conséquent, en réalité, je pense que vous vérifiez en fait plusieurs conditions. Les éléments suivants fonctionneraient également:

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

car cela signifie la même chose que:

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

Bien sûr, vous devez remplacer les valeurs des paramètres dans votre modèle. Le code ci-dessus illustre seulement le point.

[~ # ~] modifier [~ # ~] (après modification de la question)


Vous aviez raison sur le fait que le XML était horrible. En fait, c'est carrément un CodingHorror candidat! Je devais continuer à raconter pour garder une trace du nœud "Propriété" sur lequel j'étais actuellement. Je ressens ta douleur!

Voici:

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

Notez que j'ai supprimé toutes les autres vérifications (pour l'ID et la valeur). Ils ne semblent pas être nécessaires car vous pouvez arriver au nœud approprié en utilisant la hiérarchie dans le XML. De plus, vous avez déjà mentionné que la vérification de l'unicité est basée uniquement sur le contenu de l'élément long.

39
Cerebrus

Votre xpath est juste un peu hors tension:

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

Edit: Cerebrus souligne à juste titre que le code de votre OP (en utilisant la valeur implicite d'un nœud) est tout à fait correct pour vos besoins. En fait, comme il est fort probable que vous souhaitiez travailler avec le nœud "Propriété" plutôt qu'avec le nœud "long", il est probablement supérieur de demander //Property[long=$parPropId] que le text () xpath, bien que vous puissiez faire un cas pour ce dernier pour des raisons de lisibilité.

Que puis-je dire, je suis un peu fatigué aujourd'hui :)

2
annakata