2 votes

XPath pour sélectionner une liste unique d'éléments ayant un certain attribut avec Xpath 2.0

J'ai un peu de mal à obtenir une liste unique d'éléments (basée sur le nom) qui ont également un certain attribut. Je peux obtenir une liste de l'un ou l'autre de ces éléments, mais c'est la liste combinée qui me pose problème. Mon xml ressemble à ceci :

<global>
    <discipline name="tracks">
        <group name="Normal"/>
        <group name="Gloss" PackGroup="Diffuse"/>
        <group name="Mask"/>
        <group name="Diffuse"/>
        <group name="Tint" PackGroup="Gloss"/>
    </discipline>
    <discipline name="trains">
        <group name="Mask"/>
        <group name="Diffuse" PackGroup="Mask"/>
    </discipline>
</global>

Je peux obtenir une liste distincte d'éléments de groupe assez facilement en utilisant cette requête xpath :

/configuration/global/discipline/group[not(@name = following::group/@name)]

et l'obtention de la liste des éléments de groupe pour lesquels l'attribut PackGroup est défini est également triviale :

/configuration/global/discipline/group[@PackGroup]

Cependant, je ne parviens pas à obtenir une liste unique des éléments dont l'attribut PackGroup est défini. j'ai essayé ceci :

/configuration/global/discipline/group[not(@name = following::group/@name) and @PackGroup]
/configuration/global/discipline/group[not(@name = following::group/@name) and contains(@PackGroup, '*')]

qui ne renvoient aucun élément et

/configuration/global/discipline/group[not(@name = following::group/@name) and contains(@PackGroup, '')]

qui ne renvoie que la liste unique. Je ne sais pas si quelqu'un sait quelle est la requête xpath correcte pour obtenir ce que je cherche.

(je travaille en C# et en xpath 2.0 au cas où cela aurait de l'importance)

merci !

6voto

Michael Kay Points 52194

Une solution plus efficace (O(n log n) plutôt que O(n*n)) serait la suivante

for $n in distinct-values(//group[@Packgroup]/@name) 
return (//group[@Packgroup][@name=$n])[1]

2voto

LarsH Points 14726

Je pense que ce que vous recherchez est

/configuration/global/discipline/group
  [not(@name = following::group[@Packgroup]/@name) and @PackGroup]

Vous devez vous assurer que le groupe que vous filtrez (le premier group dans l'expression) et le groupe suivant que vous vérifiez (le second group ) ont un attribut @Packgroup.

Il peut également y avoir un moyen de le faire en utilisant la fonction valeurs distinctes() mais je n'ai pas encore réfléchi à la manière de le faire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X