Default XML namespace, JDOM, and XPath

北战南征 提交于 2019-11-26 10:36:29

问题


I want to use JDOM to read in an XML file, then use XPath to extract data from the JDOM Document. It creates the Document object fine, but when I use XPath to query the Document for a List of elements, I get nothing.

My XML document has a default namespace defined in the root element. The funny thing is, when I remove the default namespace, it successfully runs the XPath query and returns the elements I want. What else must I do to get my XPath query to return results?

XML:

<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<collection xmlns=\"http://www.foo.com\">
<dvd id=\"A\">
  <title>Lord of the Rings: The Fellowship of the Ring</title>
  <length>178</length>
  <actor>Ian Holm</actor>
  <actor>Elijah Wood</actor>
  <actor>Ian McKellen</actor>
</dvd>
<dvd id=\"B\">
  <title>The Matrix</title>
  <length>136</length>
  <actor>Keanu Reeves</actor>
  <actor>Laurence Fishburne</actor>
</dvd>
</collection>

Java:

public static void main(String args[]) throws Exception {
    SAXBuilder builder = new SAXBuilder();
    Document d = builder.build(\"xpath.xml\");
    XPath xpath = XPath.newInstance(\"collection/dvd\");
    xpath.addNamespace(d.getRootElement().getNamespace());
    System.out.println(xpath.selectNodes(d));
}

回答1:


XPath 1.0 doesn't support the concept of a default namespace (XPath 2.0 does). Any unprefixed tag is always assumed to be part of the no-name namespace.

When using XPath 1.0 you need something like this:

public static void main(String args[]) throws Exception {
    SAXBuilder builder = new SAXBuilder();
    Document d = builder.build("xpath.xml");
    XPath xpath = XPath.newInstance("x:collection/x:dvd");
    xpath.addNamespace("x", d.getRootElement().getNamespaceURI());
    System.out.println(xpath.selectNodes(d));
}



回答2:


I had a similiar problem, but mine was that I had a mixture of XML inputs, some of which had a namespace defined and others that didn't. To simplify my problem I ran the following JDOM snippet after loading the document.

for (Element el : doc.getRootElement().getDescendants(new ElementFilter())) {
    if (el.getNamespace() != null) el.setNamespace(null);
}

After removing all the namespaces I was able to use simple getChild("elname") style navigation or simple XPath queries.

I wouldn't recommend this technique as a general solution, but in my case it was definitely useful.




回答3:


You can also do the following

/*[local-name() = 'collection']/*[local-name() = 'dvd']/

Here is list of useful xpath queries.



来源:https://stackoverflow.com/questions/543049/default-xml-namespace-jdom-and-xpath

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!