XPath returns null for "Node" when isNameSpaceAware and isValidating are "true",

I get a node zero when I try to parse an XML file.

XPath xPath = XPathFactory.newInstance().newXPath(); Node node = null; try { node = (Node) xPath.evaluate( "/mynode", doc, XPathConstants.NODE); 

I encountered this problem only in case ...
1. DocumentBuilderFactory- setNameSpaceAware is true
2. DocumentBuilderFactory-setValidating is true.

If they are set to false, I get the correct results. Can someone help me understand what is the relation of setting these attributes to false? (I checked this question, but it is not clear my doubt)

Here is the xml -

 <?xml version="1.0" encoding="UTF-8"?> <mynode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.example.com" xsi:schemaLocation="http://www.example.com example.xsd"> <name>TargetName</name> <desc>desc goes here</desc> <pack>my.this</pack> <object>my.ExampleObject</object> <properties> <attrib> <name>id</name> <value>ZZZ</value> </attrib> <attrib> <name>ind</name> <value>X</value> </attrib> </properties> <children> <child> <name>childnodename</name> <desc>description goes here</desc> <invalues> <scope>ALL</scope> </invalues> <outvalues> <scope>ALL</scope> </outvalues> <akey> <aname>AAA</aname> <key></key> </akey> <msg> <success>code1</success> <failure>code2</failure> </msg> </child> </children> </mynode> 
+6
source share
2 answers

The quickest fix is ​​not to do setNamespaceAware(true); :-) However, if you want the namespace to know XPath, you are faced with a classic problem - XPath: is there a way to set the default namespace for queries? , in that XPath does not support the concept of a default namespace.

Therefore, your XPath must use a namespace prefix so that the query can find any nodes. However, you can set NamespaceContext to XPath to allow the namespace prefix or default namespace for the URI. One way to do this, for example:

 import java.util.*; import java.io.ByteArrayInputStream; import javax.xml.namespace.NamespaceContext; import javax.xml.parsers.*; import javax.xml.xpath.*; import org.w3c.dom.*; public class XmlParse { public static void main(String[] args) throws Exception { String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<mynode xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.example.com\" xsi:schemaLocation=\"http://www.example.com example.xsd\">" + "<name>TargetName</name>" + "</mynode>"; DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); DocumentBuilder builder = dbf.newDocumentBuilder(); Document doc = builder.parse(new ByteArrayInputStream(xml.getBytes())); final String nonameNamespace = doc.getFirstChild().getNamespaceURI(); NamespaceContext ctx = new NamespaceContext() { public String getNamespaceURI(String prefix) { String uri = null; if (prefix.equals("n")) { uri = nonameNamespace; } return uri; } @Override public Iterator getPrefixes(String val) { throw new IllegalAccessError("Not implemented!"); } @Override public String getPrefix(String uri) { throw new IllegalAccessError("Not implemented!"); } }; XPath xPath = XPathFactory.newInstance().newXPath(); xPath.setNamespaceContext(ctx); Node node = null; try { node = (Node) xPath.evaluate("/n:mynode/n:name", doc, XPathConstants.NODE); System.out.println(node.getNodeName()); System.out.println(node.getFirstChild().getNodeValue()); } catch (Exception e) { } } } 

Thus, this will resolve the default namespace ( xmlns ) to http://www.example.com when the node prefix is ​​encountered with n .

+4
source

XML is a namespace. Each XML element (and attribute) has an associated namespace; unless otherwise specified, an empty (default) namespace.

In your case, it is likely that the XML document you are trying to read is using namespaces, and your XPath query seems to only query the emtpy namespace. Therefore, you will not get the result. Be sure to use the correct namespace and it will work.

0
source

Source: https://habr.com/ru/post/893149/


All Articles