Wyodrębnij wartość węzła atrybutu za pomocą XPath

269

Jak mogę wyodrębnić wartość węzła atrybutu za pomocą XPath?

Przykładowy plik XML to:

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

Do tej pory mam ten ciąg XPath:

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

Zwraca tylko childelementy, ale chciałbym mieć wartość nameatrybutu.

W moim przykładowym pliku XML chciałbym, aby wynik był:

Child_2
Child_4
Child_1
Child_3
Rehman
źródło
Możliwy duplikat
Get

Odpowiedzi:

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

Twój oryginał child[@name]oznacza element, childktóry ma atrybut name. Chcesz child/@name.

lweller
źródło
14
Zgadzam się, pytanie brzmiało, jak uzyskać wartość atrybutu
Vladtn
5
Co jeśli chciałbym wyodrębnić tylko wartość / opis / dane znajdujące się między tagami ....
Dinu Duke
146

Aby uzyskać tylko wartość (bez nazw atrybutów), użyj string():

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

Funkcja fn: string () zwróci wartość swojego argumentu jako xs:string. Jeśli jego argumentem jest atrybut, zwróci zatem wartość atrybutu jako xs:string.

acdcjunior
źródło
1
Z xqillatym trzeba było zadzwonić xs:string. Zastanawiam się dlaczego.
krlmlr
1
@krlmlr Prawdopodobnie xsjest to przedrostek przestrzeni nazw dla funkcji XPath. Więc nie mieszają się z innymi.
acdcjunior
4
LOL. To jedyna odpowiedź, która faktycznie odpowiada na pytanie. +1
james.garriss
3
Zapewni to tylko pierwszy hit w
Xmllint
1
Co jeśli mam listę atrybutów i potrzebuję ich wartości? Wydaje się, że string () zwraca tylko pierwszą wartość.
damluar
8

Powinieneś użyć //Parent[@id='1']/Children/child/data(@name)

Atrybuty nie mogą być serializowane, więc nie można ich zwrócić w wyniku wyglądającym na xml. To, co musisz zrobić, to uzyskać dane z atrybutu za pomocą funkcji data ().

Natalia Maciejowska
źródło
7

Jak odpowiedziano powyżej:

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

wyświetli tylko nameatrybut 4 childwęzłów należących do Parentokreślonego przez predykat [@id=1]. Następnie musisz zmienić predykat, [@id=2]aby uzyskać zestaw childwęzłów na następny Parent.

Jeśli jednak Parentcałkowicie zignorujesz węzeł i użyjesz:

//child/@name

możesz wybrać nameatrybut wszystkich childwęzłów za jednym razem.

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
źródło
5
//Parent/Children[@  Attribute='value']/@Attribute

Tak jest w przypadku, gdy element ma atrybut 2, a jeden atrybut możemy uzyskać za pomocą innego.

Akshay Dubey
źródło
1

@ryenus, musisz przejrzeć wynik. Tak zrobiłbym to w 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
źródło
1

dla wszystkich xml z przestrzenią nazw użyj local-name ()

//*[local-name()='Parent'][@id='1']/*[local-name()='Children']/*[local-name()='child']/@name 
Ed Bangga
źródło