Extrair valor do nó do atributo via XPath

270

Como posso extrair o valor de um nó de atributo via XPath?

Um arquivo XML de amostra é:

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

Até agora eu tenho essa string XPath:

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

Ele retorna apenas childelementos, mas eu gostaria de ter o valor do nameatributo.

Para o meu arquivo XML de amostra, eis o que eu gostaria que fosse a saída:

Child_2
Child_4
Child_1
Child_3
Rehman
fonte
Possível duplicata do atributo Obtendo usando XPath
tripleee

Respostas:

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

Seu original child[@name]significa um elemento childque possui um atributo name. Você quer child/@name.

morador
fonte
14
Concordo, a questão era como obter o valor do atributo
Vladtn
5
E se eu gostaria de extrair apenas o valor / descrição / dados presente entre as tags ....
Dinu Duke
147

Para obter apenas o valor (sem nomes de atributo), use string():

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

A função fn: string () retornará o valor de seu argumento como xs:string. Caso seu argumento seja um atributo, ele retornará o valor do atributo como xs:string.

acdcjunior
fonte
1
Com xqillaisso foi necessário ligar xs:string. Eu quero saber porque.
Krlmlr
1
@krlmlr Provavelmente xsé o prefixo do namespace para as funções XPath. Então eles não estão confusos com os outros.
Acdcjunior 22/07/2013
4
RI MUITO. Esta é a única resposta que realmente responde à pergunta. 1
james.garriss
3
Isso fornecerá apenas o primeiro hit no xmllint #
crazyduck 27/06/19
1
E se eu tiver uma lista de atributos e precisar dos valores deles? string () parece retornar apenas o primeiro valor.
damluar 18/09/19
9

Você deveria usar //Parent[@id='1']/Children/child/data(@name)

Os atributos não podem ser serializados, portanto você não pode devolvê-los em um resultado com aparência de xml. O que você precisa fazer é obter os dados do atributo usando a função data ().

Natalia Maciejowska
fonte
9

Como respondido acima:

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

produzirá apenas o nameatributo dos 4 childnós pertencentes ao Parentespecificado por seu predicado [@id=1]. Você precisará alterar o predicado [@id=2]para obter o conjunto de childnós para o próximo Parent.

No entanto, se você ignorar Parentcompletamente o nó e usar:

//child/@name

você pode selecionar o nameatributo de todos os childnós de uma só vez.

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
fonte
6
//Parent/Children[@  Attribute='value']/@Attribute

Este é o caso que pode ser usado em que o elemento possui 2 atributos e podemos obter um atributo com a ajuda de outro.

Akshay Dubey
fonte
3

@ryenus, você precisa percorrer o resultado. É assim que eu faria em 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
fonte
3

para todo xml com espaço para nome, use local-name ()

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