XPath con espacio de nombres en Java

6 minutos de lectura

XPath con espacio de nombres en Java
Sergio

Me gustaría obtener todo el contenido entre las etiquetas, pero no sé cómo hacerlo debido a la urna: espacio de nombres.

<urn:ResponseStatus version="1.0" xmlns:urn="urn:camera-org">

<urn:requestURL>/CAMERA/Streaming/status</urn:requestURL>
<urn:statusCode>4</urn:statusCode>
<urn:statusString>Invalid Operation</urn:statusString>
<urn:id>0</urn:id>

</urn:ResponseStatus>

¿Algunas ideas?

  • ¿Qué biblioteca estás usando? ¿Ha intentado prefijar su consulta con urn: ?

    – Olivier Roger

    04 dic.

  • Usando javax.xml.xpath.XPath; Lo he intentado con urn: pero eso no ayudó.

    – Sergio

    04 dic.


XPath con espacio de nombres en Java
Alex

  1. Respuesta corta: usa XPath local-name(). Como esto: xPathFactory.newXPath().compile("//*[local-name()='requestURL']/text()"); regresará /CAMERA/Streaming/status
  2. O puede implementar un NamespaceContext que asigna nombres de espacios de nombres y URI y lo configura en el objeto XPath antes de realizar la consulta.
  3. Mira esto artículo de blog, Actualizar: el artículo está caído, puedes verlo en archivo web

Solución 1 muestra:

XPath xpath = XPathFactory.newInstance().newXPath();
String responseStatus = xpath.evaluate("//*[local-name()='ResponseStatus']/text()", document);
System.out.println("-> " + responseStatus);

Muestra de la solución 2:

// load the Document
Document document = ...;
NamespaceContext ctx = new NamespaceContext() {
    public String getNamespaceURI(String prefix) {
        return prefix.equals("urn") ? "urn:camera-org" : null; 
    }
    public Iterator getPrefixes(String val) {
        return null;
    }
    public String getPrefix(String uri) {
        return null;
    }
};
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(ctx);
String responseStatus = xpath.evaluate("//urn:ResponseStatus/text()", document);
System.out.println("-> " + responseStatus);

Editar

Este es un ejemplo completo, recupera correctamente el elemento:

String xml = "<urn:ResponseStatus version="1.0" xmlns:urn="urn:camera-org">rn" + //
        "rn" + //
        "<urn:requestURL>/CAMERA/Streaming/status</urn:requestURL>rn" + //
        "<urn:statusCode>4</urn:statusCode>rn" + //
        "<urn:statusString>Invalid Operation</urn:statusString>rn" + //
        "<urn:id>0</urn:id>rn" + //
        "rn" + //
        "</urn:ResponseStatus>";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new java.io.ByteArrayInputStream(xml.getBytes()));
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(new NamespaceContext() {
    public String getNamespaceURI(String prefix) {
        return prefix.equals("urn") ? "urn:camera-org" : null;
    }

    public Iterator<?> getPrefixes(String val) {
        return null;
    }

    public String getPrefix(String uri) {
        return null;
    }
});
XPathExpression expr = xpath.compile("//urn:ResponseStatus");
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
for (int i = 0; i < nodes.getLength(); i++) {
    Node currentItem = nodes.item(i);
    System.out.println("found node -> " + currentItem.getLocalName() + " (namespace: " + currentItem.getNamespaceURI() + ")");
}

  • ¡Buena respuesta! (Esa publicación de blog habría sido más útil si el código tuviera sangría y el XML de ejemplo no hubiera sido consumido por su propio servidor. Bueno, sigue siendo una lista útil al final).

    – Ti Strga

    07 mar. 13 a las 20:30

  • Gracias una tonelada !! Analicé un enorme archivo xml complejo usando esta lógica y funcionó para mí.

    – Sandeep Singh

    28 sep.

  • getNamespaceURI debería estar regresando XMLConstants.NULL_NS_URI (que es una cadena vacía) en lugar de nulo cuando no coincide con ningún prefijo registrado.

    – Jules

    23 ago. 17 en 07:35

  • El blog.davber.com El sitio web solo devuelve un error interno del servidor ahora.

    – gancho

    08 feb. 18 a las 22:42

  • Todos: actualicé la respuesta con un enlace a la publicación original del blog en el punto 3 a través del archivo web

    – Alex

    12 feb. 18 en 11:09

XPath con espacio de nombres en Java
Yash

XML xpath con espacio de nombres

XML sencillo

String namespaceXML = "<?xml version='1.0' ?><information><person id='1'><name>Deep</name><age>34</age><gender>Male</gender></person>  <person id='2'><name>Kumar</name><age>24</age><gender>Male</gender></person> <person id='3'><name>Deepali</name><age>19</age><gender>Female</gender></person><!-- more persons... --></information>";
String jsonString = "{}";
String expression = "//information";

Espacio de nombres XML

String namespaceXML = "<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><m:NumberToDollarsResponse xmlns:m="http://www.dataaccess.com/webservicesserver/"><m:NumberToDollarsResult>nine hundred and ninety nine dollars</m:NumberToDollarsResult></m:NumberToDollarsResponse></soap:Body></soap:Envelope>";
String jsonString = "{'soap':'http://schemas.xmlsoap.org/soap/envelope/', 'm':'http://www.dataaccess.com/webservicesserver/'}";
String expression = "//m:NumberToDollarsResponse/m:NumberToDollarsResult/text()";

Proporcione el archivo xml del espacio de nombres como una cadena, para asscerionXpath(namespaceXML, jsonString, expression) método y obtenga el resultado en forma de texto/nodo.

texto() : nine hundred and ninety nine dollars

nodo:
<m:NumberToDollarsResult xmlns:m="http://www.dataaccess.com/webservicesserver/">
nine hundred and ninety nine dollars
</m:NumberToDollarsResult>

public static String asscerionXpath(String namespaceXML, String jsonString, String expression){
    if(namespaceXML.indexOf("><") > -1) namespaceXML = namespaceXML.replace("><", ">rn<");
    if(jsonString.indexOf("'") > -1)    jsonString = jsonString.replace("'", """);

    System.out.println("namespaceXML : n"+namespaceXML);
    System.out.println("nsmespaces : n"+jsonString);

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setValidating(false);
    factory.setNamespaceAware(true);
    factory.setIgnoringComments(true);
    factory.setIgnoringElementContentWhitespace(true);
    try {
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document source = builder.parse( string2Source(namespaceXML) );
        XPath xpath = XPathFactory.newInstance().newXPath();

        addNameSpaces(jsonString, xpath);
        // An XPath expression is not thread-safe. Make sure it is accessible by only one Thread.
        XPathExpression expr = xpath.compile(expression);

        // The NodeList interface provides the abstraction of an ordered collection of nodes,
        NodeList nodes = (org.w3c.dom.NodeList) expr.evaluate(source, XPathConstants.NODESET);;
        Node tree_base = nodes.item(0);
        return document2String(tree_base);
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (SAXException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ParserConfigurationException e) {
        e.printStackTrace();
    } catch (XPathExpressionException e) {
        System.out.println("If the expression cannot be evaluated.");
    }
    return "";
}
static InputSource string2Source( String str ) {
    InputSource inputSource = new InputSource( new StringReader( str ) );
    return inputSource;
}
static void addNameSpaces(String jsonString, XPath xpath) {
    JSONParser parser = new JSONParser();
    try {
        JSONObject namespaces = (JSONObject) parser.parse(jsonString);

        if (namespaces.size() > 0) {
            final JSONObject declaredPrefix = namespaces; // To access in Inner-class.
            NamespaceContext nameSpace = new NamespaceContext() {
                // To get all prefixes bound to a Namespace URI in the current scope, XPath 1.0 specification
                // --> "no prefix means no namespace"
                public String getNamespaceURI(String prefix) {
                    Iterator<?> key = declaredPrefix.keySet().iterator();
                    System.out.println("Keys : "+key.toString());
                    while (key.hasNext()) {
                        String name = key.next().toString();
                        if (prefix.equals(name)) {
                            System.out.println(declaredPrefix.get(name));
                            return declaredPrefix.get(name).toString();
                        }
                    }
                    return "";
                }
                public Iterator<?> getPrefixes(String val) {
                    return null;
                }
                public String getPrefix(String uri) {
                    return null;
                }
            };// Inner class.

            xpath.setNamespaceContext( nameSpace );
        }

    } catch ( org.json.simple.parser.ParseException e) {
        e.printStackTrace();
    }
}

.

¿Ha sido útil esta solución?