Obteniendo atributo usando XPath

344

Dada una estructura 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>

¿Cómo podría obtener el valor de lang(dónde langestá engen el título del libro), para el primer elemento?

GurdeepS
fuente

Respuestas:

472

¿Cómo podría obtener el valor de lang (donde lang = eng en el título del libro), para el primer elemento?

Uso :

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

Esto significa :

Seleccione el langatributo del elemento de título que es un elemento secundario del primer elemento booksecundario del elemento superior del documento XML.

Para obtener solo el valor de cadena de este atributo, use la función XPath estándarstring() :

string(/*/book[1]/title/@lang)
Dimitre Novatchev
fuente
3
@AbhishekAsthana, el resultado de evaluar la expresión XPath produce exactamente el valor de cadena del langatributo. Si el atributo no contiene corchetes, no serán parte del resultado de la evaluación de la expresión XPath. Supongo que estos son agregados por una herramienta (inapropiada) que está utilizando.
Dimitre Novatchev
66
sí, descubrí el problema ... así es como soapUI lo muestra, pero esos corchetes no se usan cuando uso el valor xpath. He visto esto mucho tiempo. El problema no está en la herramienta ... se encuentra entre la silla y el teclado.
Abhishek Asthana
44
@KorayTugay, la expresión XPath /*/book[1]/title/@lang selecciona un conjunto de nodos de 0 o más nodos de atributos, mientras que la expresión XPath string(/*/book[1]/title/@lang)cuando se evalúa, produce el valor de cadena de este conjunto de nodos, y este es el valor de cadena del primero (en orden de documento) nodo de este conjunto de nodos.
Dimitre Novatchev
44
@KorayTugay, No, la primera expresión selecciona , no "devuelve": un conjunto de nodos, y este conjunto de nodos no es una cadena. Un nodo no es una cadena: un nodo es un nodo en un árbol . Un documento XML es un árbol de nodos. lang="eng"es solo una de las muchas representaciones textuales de un nodo de atributo que tiene un nombre "lang", no pertenece a un espacio de nombres y tiene un valor de cadena la cadena "eng"
Dimitre Novatchev
1
@Vladimir, si la v corresponde a un uri de espacio de nombres de decir: "my: vvv", entonces se puede crear en el host del motor XPath utilizando una asignación que asocia myPrefix (puede ser v pero no necesario) al mismo espacio de nombres -uri "mi: vvv". Y luego el atributo será seleccionado usando: title / @ myPrefix: lang. La forma en que se crea dicha asignación es específica de la implementación y uno tiene que leer la documentación del host del motor XPath. Esto se hace de una manera específica en .NET y de otra manera, digamos en Saxon. Si no tiene ninguna asignación de este tipo, use: title / @ * [name () = 'v: lang']
Dimitre Novatchev
47

¡Gracias! Esto resolvió un problema similar que tuve con un atributo de datos dentro de un 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 esto ayude a alguien más!

smulldino
fuente
6

Puedes probar debajo del patrón xPath,

  XPathExpression expr = xPath.compile("/bookstore/book/title[@lang='eng']")
Sharath
fuente
55
Eso seleccionará cualquier elemento de título XML en / bookstore / book que tenga un atributo lang con el valor eng, NO el valor de lang. es decir, selecciona una lista de elementos, no un solo atributo
JFK
2

También puedes conseguirlo

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

aunque si está utilizando XMLDOM con JavaScript, puede codificar algo como

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

y n1.textte dará el valor"eng"

Vinod Srivastav
fuente
2

puedes usar:

(//@lang)[1]

esto significa que obtienes todos los nodos de atributos con un nombre igual a "lang" y obtienes el primero.

Starcwl
fuente
0

Aquí está el fragmento de obtener el valor de atributo de "lang" con XPath y 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());
    }
}
vtd-xml-author
fuente
0

Si está utilizando PostgreSQL, esta es la forma correcta de obtenerlo. Esto es solo una suposición en la que tiene una tabla de libros TÍTULO y una columna PRECIO con datos poblados. Aquí está la consulta

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