Extraire la valeur du nœud d'attribut via XPath

270

Comment puis-je extraire la valeur d'un nœud d'attribut via XPath?

Un exemple de fichier XML est:

<parents name='Parents'>
  <Parent id='1' name='Parent_1'>
    <Children name='Children'>
      <child name='Child_2' id='2'>child2_Parent_1</child>
      <child name='Child_4' id='4'>child4_Parent_1</child>
      <child name='Child_1' id='3'>child1_Parent_1</child>
      <child name='Child_3' id='1'>child3_Parent_1</child>
    </Children>
  </Parent>
  <Parent id='2' name='Parent_2'>
    <Children name='Children'>
      <child name='Child_1' id='8'>child1_parent2</child>
      <child name='Child_2' id='7'>child2_parent2</child>
      <child name='Child_4' id='6'>child4_parent2</child>
      <child name='Child_3' id='5'>child3_parent2</child>
    </Children>
  </Parent>
</parents>

Jusqu'à présent, j'ai cette chaîne XPath:

//Parent[@id='1']/Children/child[@name]  

Il ne renvoie que des childéléments, mais j'aimerais avoir la valeur de l' nameattribut.

Pour mon exemple de fichier XML, voici ce que j'aimerais que la sortie soit:

Child_2
Child_4
Child_1
Child_3
Rehman
la source
Copie

Réponses:

351
//Parent[@id='1']/Children/child/@name 

Votre original child[@name]signifie un élément childqui a un attribut name. Tu veux child/@name.

lweller
la source
14
Je suis d'accord, la question était de savoir comment obtenir la valeur de l'attribut
Vladtn
5
Que faire si je souhaite extraire uniquement la valeur / description / données présentes entre les balises ....
Dinu Duke
147

Pour obtenir uniquement la valeur (sans les noms d'attribut), utilisez string():

string(//Parent[@id='1']/Children/child/@name)

La fonction fn: string () renverra la valeur de son argument comme xs:string. Dans le cas où son argument est un attribut, il retournera donc la valeur de l'attribut comme xs:string.

acdcjunior
la source
1
Avec xqillail fallait appeler xs:string. Je me demande pourquoi.
krlmlr du
1
@krlmlr xsest probablement le préfixe d'espace de noms pour les fonctions XPath. Ils ne sont donc pas mélangés avec les autres.
acdcjunior du
4
LOL. C'est la seule réponse qui répond réellement à la question. +1
james.garriss
3
Cela ne fournira que le premier hit dans xmllint
crazyduck
1
Et si j'ai une liste d'attributs et j'ai besoin de leurs valeurs? string () semble renvoyer uniquement la première valeur.
damluar
9

Tu devrais utiliser //Parent[@id='1']/Children/child/data(@name)

Les attributs ne peuvent pas être sérialisés, vous ne pouvez donc pas les renvoyer dans un résultat au format xml. Ce que vous devez faire est d'obtenir les données de l'attribut à l'aide de la fonction data ().

Natalia Maciejowska
la source
9

Comme répondu ci-dessus:

//Parent[@id='1']/Children/child/@name 

ne sortira que l' nameattribut des 4 childnœuds appartenant au Parentspécifié par son prédicat [@id=1]. Vous devrez ensuite modifier le prédicat [@id=2]pour obtenir l'ensemble de childnœuds pour le prochainParent .

Cependant, si vous ignorez Parentcomplètement le nœud et utilisez:

//child/@name

vous pouvez sélectionner l' nameattribut de tous les childnœuds en une seule fois.

name="Child_2"
name="Child_4"
name="Child_1"
name="Child_3"
name="Child_1"
name="Child_2"
name="Child_4"
name="Child_3"
Vinod Srivastav
la source
6
//Parent/Children[@  Attribute='value']/@Attribute

C'est le cas qui peut être utilisé lorsque l'élément a 2 attributs et que nous pouvons obtenir un attribut à l'aide d'un autre.

Akshay Dubey
la source
3

@ryenus, vous devez parcourir le résultat. Voici comment je le ferais en vbscript;

Set xmlDoc = CreateObject("Msxml2.DOMDocument")
xmlDoc.setProperty "SelectionLanguage", "XPath"
xmlDoc.load("kids.xml")

'Remove the id=1 attribute on Parent to return all child names for all Parent nodes
For Each c In xmlDoc.selectNodes ("//Parent[@id='1']/Children/child/@name")
    Wscript.Echo c.text
Next
NickC
la source
3

pour tout xml avec espace de noms, utilisez local-name ()

//*[local-name()='Parent'][@id='1']/*[local-name()='Children']/*[local-name()='child']/@name 
Ed Bangga
la source