What am I doing wrong with XPath?
I am trying to manipulate xsd schema as an xml document that should not be a problem, I believe. But facing troubles with XPath. Whatever XPath I try, it returns nothing. Tried it with or without namespaces but no success. Please help me understand what am I doing wrong?
My xml is:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.mydomain.com" xmlns="http://www.mydomain.com" elementFormDefault="qualified">
<xs:complexType name="Label">
<xs:choice maxOccurs="unbounded" minOccurs="0">
<xs:element name="Listener"/>
</xs:choice>
</xs:complexType>
</xs:schema>
and application code is:
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setValidating(false);
domFactory.setNamespaceAware(true);
domFactory.setIgnoringComments(true);
domFactory.setIgnoringElementContentWhitespace(true);
try {
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document dDoc = builder.parse("C:/Temp/test.xsd");
// This part works
Node rootNode = dDoc.getElementsByTagName("xs:schema").item(0);
System.out.println(rootNode.getNodeName());
// This part doesn't work
XPath xPath1 = XPathFactory.newInstance().newXPath();
NodeList nList1 = (NodeList) xPath1.evaluate("//xs:schema", dDoc, XPathConstants.NODESET);
System.out.println(nList1.item(0).getNodeName());
// This part doesn't work
XPath xPath2 = XPathFactory.newInstance().newXPath();
NodeList nList2 = (NodeList) xPath2.evaluate("//xs:element", rootNode, XPathConstants.NODESET);
System.out.println(nList2.item(0).g开发者_运维百科etNodeName());
}catch (Exception e){
e.printStackTrace();
}
Set a namespace context using XPath.setNamespaceContext(). This binds the xs
prefix to the http://www.w3.org/2001/XMLSchema
namespace.
Made changes to your code. It works:
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class XPathtest {
public static void main(String[] args) {
DocumentBuilderFactory domFactory = DocumentBuilderFactory
.newInstance();
domFactory.setValidating(false);
domFactory.setNamespaceAware(true);
domFactory.setIgnoringComments(true);
domFactory.setIgnoringElementContentWhitespace(true);
try {
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document dDoc = builder.parse("C:/Temp/test.xsd");
// This part works
Node rootNode = dDoc.getElementsByTagName("xs:schema").item(0);
System.out.println(rootNode.getNodeName());
// This part doesn't work
XPath xPath1 = XPathFactory.newInstance().newXPath();
NamespaceContext nsContext = new NamespaceContext() {
@Override
public String getNamespaceURI(String prefix) {
return "http://www.w3.org/2001/XMLSchema";
}
@Override
public String getPrefix(String namespaceURI) {
return "xs";
}
@Override
public Iterator getPrefixes(String namespaceURI) {
Set s = new HashSet();
s.add("xs");
return s.iterator();
}
};
xPath1.setNamespaceContext((NamespaceContext) nsContext);
NodeList nList1 = (NodeList) xPath1.evaluate("//xs:schema", dDoc,
XPathConstants.NODESET);
System.out.println(nList1.item(0).getNodeName());
// This part doesn't work
// XPath xPath2 = XPathFactory.newInstance().newXPath();
NodeList nList2 = (NodeList) xPath1.evaluate("//xs:element",
rootNode, XPathConstants.NODESET);
System.out.println(nList2.item(0).getNodeName());
} catch (Exception e) {
e.printStackTrace();
}
}
}
The reason is that you haven't specified what xs
means. An xml parser must know the namespace url, xs
is just an identifier.
You can demonstrate this yourself by using the following code:
XPath xPath = XPathFactory.newInstance().newXPath();
SimpleNamespaceContext nsContext = new SimpleNamespaceContext();
nsContext.addNamespace("t", "http://www.w3.org/2001/XMLSchema");
xPath.setNamespaceContext(nsContext);
xPath.evaluate("//t:schema", dDoc, XPathConstants.NODESET);
You can see that I now use the identifier t
instead of xs
but that doesn't matter as long as you use the same namespace url.
精彩评论