Obtendo atributo usando XPath

344

Dada uma estrutura XML como esta:

<?xml version="1.0" encoding="ISO-8859-1"?>

<bookstore>

<book>
  <title lang="eng">Harry Potter</title>
  <price>29.99</price>
</book>

<book>
  <title lang="eng">Learning XML</title>
  <price>39.95</price>
</book>

</bookstore>

Como eu poderia obter o valor de lang(onde langestá o engtítulo do livro), para o primeiro elemento?

GurdeepS
fonte

Respostas:

472

Como eu poderia obter o valor de lang (onde lang = eng no título do livro), para o primeiro elemento?

Use :

/*/book[1]/title/@lang

Isto significa :

Selecione o langatributo do elemento title que é filho do primeiro bookfilho do elemento superior do documento XML.

Para obter apenas o valor da sequência deste atributo, use a função XPath padrãostring() :

string(/*/book[1]/title/@lang)
Dimitre Novatchev
fonte
3
@AbhishekAsthana, O resultado da avaliação da expressão XPath produz exatamente o valor da string do langatributo. Se o atributo não contiver colchetes, eles não farão parte do resultado da avaliação da expressão XPath. Meu palpite é que eles foram adicionados por uma ferramenta (inadequada) que você está usando.
Dimitre Novatchev
6
Sim, eu descobri o problema ... é assim que o soapUI o exibe, mas esses colchetes não são usados ​​quando eu uso o valor xpath. Eu vejo isso há muito tempo. O problema não é com a ferramenta .. está entre a cadeira e o teclado.
Abhishek Asthana
4
@KorayTugay, a expressão XPath /*/book[1]/title/@lang seleciona um conjunto de nós de 0 ou mais nós de atributo, enquanto a expressão XPath, string(/*/book[1]/title/@lang)quando avaliada, produz o valor da cadeia de caracteres deste conjunto de nós - e este é o valor da cadeia de caracteres do primeiro (na ordem dos documentos) nó deste conjunto de nós.
Dimitre Novatchev
4
@KorayTugay, Não, a primeira expressão seleciona , não "retorna" - um conjunto de nós, e esse conjunto de nós não é uma string. Um nó não é uma cadeia - um nó é um nó em uma árvore . Um documento XML é uma árvore de nós. lang="eng"é apenas uma das muitas representações textuais de um nó de atributo que tem um nome "lang", não pertence a um espaço de nomes, e tem um valor de string do "eng" string
Dimitre Novatchev
11
@ Vladimir, Se v corresponde a um namespace-uri, digamos: "my: vvv", é possível criar no host do mecanismo XPath um mapeamento associando myPrefix (pode ser v, mas não necessário) para o mesmo namespace -uri "meu: vvv". E o atributo será selecionado usando: title / @ myPrefix: lang. Como esse mapeamento é criado é específico da implementação e é necessário ler a documentação do host do mecanismo XPath. Isso é feito de uma maneira específica no .NET e de outra maneira, digamos no saxão. Se você não tiver esse mapeamento, use: title / @ * [name () = 'v: lang']
Dimitre Novatchev
47

Obrigado! Isso resolveu um problema semelhante que tive com um atributo de dados dentro de uma div.

<div id="prop_sample" data-want="data I want">data I do not want</div>

Use este xpath: //*[@id="prop_sample"]/@data-want

Espero que isso ajude alguém!

smulldino
fonte
6

Você pode tentar abaixo do padrão xPath,

  XPathExpression expr = xPath.compile("/bookstore/book/title[@lang='eng']")
Sharath
fonte
5
Isso selecionará qualquer elemento de título XML em / bookstore / book que tenha um Atributo lang com o valor eng, NÃO o valor de lang. ou seja, ele seleciona uma lista de elementos, não um único Atributo
JFK
2

Você também pode obtê-lo

string(//bookstore/book[1]/title/@lang)    
string(//bookstore/book[2]/title/@lang)

embora, se você estiver usando XMLDOM com JavaScript, possa codificar algo como

var n1 = uXmlDoc.selectSingleNode("//bookstore/book[1]/title/@lang");

e n1.textlhe dará o valor"eng"

Vinod Srivastav
fonte
2

você pode usar:

(//@lang)[1]

isso significa que você obtém todos os nós de atributos com nome igual a "lang" e obtém o primeiro.

starcwl
fonte
0

Aqui está o trecho de como obter o valor do atributo "lang" com XPath e VTD-XML.

import com.ximpleware.*;
public class getAttrVal {
    public static void main(String s[]) throws VTDException{
        VTDGen vg = new VTDGen();
        if (!vg.parseFile("input.xml", false)){
            return ;
        }
        VTDNav vn = vg.getNav();
        AutoPilot ap = new AutoPilot(vn);
        ap.selectXPath("/bookstore/book/title/@lang");
        System.out.println(" lang's value is ===>"+ap.evalXPathToString());
    }
}
Autor do vtd-xml
fonte
0

Se você estiver usando o PostgreSQL, este é o caminho certo para obtê-lo. Essa é apenas uma suposição em que, como você tem uma coluna TITLE e PRICE da tabela de livros com dados preenchidos. Aqui está a consulta

SELECT xpath('/bookstore/book/title/@lang', xmlforest(book.title AS title, book.price AS price), ARRAY[ARRAY[]::TEXT[]]) FROM book LIMIT 1;
Royce
fonte