322

How can I extract the value of an attribute node via XPath?

A sample XML file is:

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

So far I have this XPath string:

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

It returns only child elements, but I would like to have the value of the name attribute.

For my sample XML file, here's what I'd like the output to be:

Child_2
Child_4
Child_1
Child_3
DavidRR
  • 18,291
  • 25
  • 109
  • 191
Rehman
  • 3,908
  • 6
  • 28
  • 29
  • Possible duplicate of [Getting attribute using XPath](http://stackoverflow.com/questions/4531995/getting-attribute-using-xpath) – tripleee Dec 03 '15 at 08:53

8 Answers8

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

Your original child[@name] means an element child which has an attribute name. You want child/@name.

Rory O'Kane
  • 29,210
  • 11
  • 96
  • 131
lweller
  • 11,077
  • 3
  • 34
  • 38
176

To get just the value (without attribute names), use string():

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

The fn:string() fucntion will return the value of its argument as xs:string. In case its argument is an attribute, it will therefore return the attribute's value as xs:string.

Flow
  • 23,572
  • 15
  • 99
  • 156
acdcjunior
  • 132,397
  • 37
  • 331
  • 304
10

As answered above:

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

will only output the name attribute of the 4 child nodes belonging to the Parent specified by its predicate [@id=1]. You'll then need to change the predicate to [@id=2] to get the set of child nodes for the next Parent.

However, if you ignore the Parent node altogether and use:

//child/@name

you can select name attribute of all child nodes in one go.

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
  • 3,644
  • 1
  • 27
  • 40
  • 3
    Yes ... but the question is how to return only the attribute value: `Child_2` etc. The reason I'm here is I managed to get as far as you got, I want just the attribute values, I used Google, and arrived at this question. – reinierpost Sep 05 '22 at 08:02
  • 1
    @reinierpost It depend the xml engine in use if you see here http://xpather.com/VZDuaXsb and in javascript its just `node.text` https://stackoverflow.com/a/35726551/3057246 – Vinod Srivastav Nov 09 '22 at 20:10
9

You should use //Parent[@id='1']/Children/child/data(@name)

The attributes can not be serialized so you can't return them in an xml looking result. What you need to do is obtain the data from the attribute using data() function.

abatishchev
  • 98,240
  • 88
  • 296
  • 433
6
//Parent/Children[@  Attribute='value']/@Attribute

This is the case which can be used where element is having 2 attribute and we can get the one attribute with the help of another one.

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
Akshay Dubey
  • 79
  • 1
  • 4
6

for all xml with namespace use local-name()

//*[local-name()='Parent'][@id='1']/*[local-name()='Children']/*[local-name()='child']/@name 
Ed Bangga
  • 12,879
  • 4
  • 16
  • 30
4

@ryenus, You need to loop through the result. This is how I'd do it in 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
abatishchev
  • 98,240
  • 88
  • 296
  • 433
NickC
  • 65
  • 1
4

Here is the standard formula to extract the values of attribute and text using XPath-

  1. To extract attribute value for Web Element-

    elementXPath/@attributeName

  2. To extract text value for Web Element-

    elementXPath/text()

In your case here is the xpath which will return

//parent[@name='Parent_1']//child/@name

It will return:

Child_2
Child_4
Child_1
Child_3