xmlns vinculado utiliza ser qué que proyecto prefijo para nombres namespace lectura está espacio error definido debe xml xpath xml-namespaces

vinculado - ¿Cómo trata XPath con los espacios de nombres XML?



qué es el xmlns (1)

¿Cómo trata XPath con los espacios de nombres XML?

Si yo uso

/IntuitResponse/QueryResponse/Bill/Id

para analizar el documento XML a continuación me devuelven 0 nodos.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <IntuitResponse xmlns="http://schema.intuit.com/finance/v3" time="2016-10-14T10:48:39.109-07:00"> <QueryResponse startPosition="1" maxResults="79" totalCount="79"> <Bill domain="QBO" sparse="false"> <Id>=1</Id> </Bill> </QueryResponse> </IntuitResponse>

Sin embargo, no estoy especificando el espacio de nombres en XPath (es decir, http://schema.intuit.com/finance/v3 no es un prefijo de cada token de la ruta). ¿Cómo puede XPath saber qué Id quiero si no lo digo explícitamente? Supongo que en este caso (dado que solo hay un espacio de nombres) XPath podría saltarse ignorando completamente los xmlns . Pero si hay múltiples espacios de nombres, las cosas podrían ponerse feas.


Definición de espacios de nombres en XPath (recomendado)

XPath en sí no tiene una forma de vincular un prefijo de espacio de nombres con un espacio de nombres. Dichas instalaciones son proporcionadas por la biblioteca de alojamiento.

Se recomienda que use esas facilidades y defina prefijos de espacio de nombres que luego se puedan usar para calificar los nombres de elementos y atributos XML según sea necesario.

Estos son algunos de los diversos mecanismos que los hosts XPath proporcionan para especificar enlaces de prefijo de espacio de nombres a URI de espacio de nombres:

XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:i="http://schema.intuit.com/finance/v3"> ...

Perl ( LibXML ):

my $xc = XML::LibXML::XPathContext->new($doc); $xc->registerNs(''i'', ''http://schema.intuit.com/finance/v3''); my @nodes = $xc->findnodes(''/i:IntuitResponse/i:QueryResponse'');

Python ( lxml ):

from lxml import etree f = StringIO(''<IntuitResponse>...</IntuitResponse>'') doc = etree.parse(f) r = doc.xpath(''/i:IntuitResponse/i:QueryResponse'', namespaces={''i'':''http://schema.intuit.com/finance/v3''})

Python ( ElementTree ):

namespaces = {''i'': ''http://schema.intuit.com/finance/v3''} root.findall(''/i:IntuitResponse/i:QueryResponse'', namespaces)

Java (SAX):

NamespaceSupport support = new NamespaceSupport(); support.pushContext(); support.declarePrefix("i", "http://schema.intuit.com/finance/v3");

Java (XPath):

xpath.setNamespaceContext(new NamespaceContext() { public String getNamespaceURI(String prefix) { switch (prefix) { case "i": return "http://schema.intuit.com/finance/v3"; // ... } });

xmlstarlet:

-N i="http://schema.intuit.com/finance/v3"

JavaScript:

Consulte Implementación de un solucionador de espacio de nombres definido por el usuario :

function nsResolver(prefix) { var ns = { ''i'' : ''http://schema.intuit.com/finance/v3'' }; return ns[prefix] || null; } document.evaluate( ''/i:IntuitResponse/i:QueryResponse'', document, nsResolver, XPathResult.ANY_TYPE, null );

PhP:

Adaptado de la respuesta de @ Tomalak usando DOMDocument :

$result = new DOMDocument(); $result->loadXML($xml); $xpath = new DOMXpath($result); $xpath->registerNamespace("i", "http://schema.intuit.com/finance/v3"); $result = $xpath->query("/i:IntuitResponse/i:QueryResponse");

Consulte también las preguntas y respuestas canónicas de @ IMSoP sobre los espacios de nombres PHP SimpleXML .

DO#:

XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable); nsmgr.AddNamespace("i", "http://schema.intuit.com/finance/v3"); XmlNodeList nodes = el.SelectNodes(@"/i:IntuitResponse/i:QueryResponse", nsmgr);

VBA:

xmlNS = "xmlns:i=''http://schema.intuit.com/finance/v3''" doc.setProperty "SelectionNamespaces", xmlNS Set queryResponseElement =doc.SelectSingleNode("/i:IntuitResponse/i:QueryResponse")

VB.NET:

xmlDoc = New XmlDocument() xmlDoc.Load("file.xml") nsmgr = New XmlNamespaceManager(New XmlNameTable()) nsmgr.AddNamespace("i", "http://schema.intuit.com/finance/v3"); nodes = xmlDoc.DocumentElement.SelectNodes("/i:IntuitResponse/i:QueryResponse", nsmgr)

Rubí (Nokogiri):

puts doc.xpath(''/i:IntuitResponse/i:QueryResponse'', ''i'' => "http://schema.intuit.com/finance/v3")

Tenga en cuenta que Nokogiri admite la eliminación de espacios de nombres,

doc.remove_namespaces!

pero vea las advertencias a continuación que desalientan la derrota de los espacios de nombres XML.

Una vez que haya declarado un prefijo de espacio de nombres, puede escribir su XPath para usarlo:

/i:IntuitResponse/i:QueryResponse

Derrotando espacios de nombres en XPath (no recomendado)

Una alternativa es escribir predicados que prueben contra local-name() :

/*[local-name()=''IntuitResponse'']/*[local-name()=''QueryResponse'']/@startPosition

O, en XPath 2.0:

/*:IntuitResponse/*:QueryResponse/@startPosition

Bordear espacios de nombres de esta manera funciona pero no se recomienda porque

  • Sub-especifica el nombre completo del elemento / atributo.
  • No puede diferenciar entre los nombres de elementos / atributos en diferentes espacios de nombres (el propósito mismo de los espacios de nombres). Tenga en cuenta que esta preocupación podría abordarse agregando un predicado adicional para verificar el URI del espacio de nombres explícitamente 1 :

    /*[ namespace-uri()=''http://schema.intuit.com/finance/v3'' and local-name()=''IntuitResponse''] /*[ namespace-uri()=''http://schema.intuit.com/finance/v3'' and local-name()=''QueryResponse''] /@startPosition

    1 Gracias a Daniel Haley por la nota namespace-uri() .

  • Es excesivamente detallado.