JDOM2 with XPath doesn't work with namespace

本秂侑毒 提交于 2020-01-03 19:45:27

问题


Attempting to use XPath with an XML file that has a default namespace declared for the root node.

Example code:

    final SAXBuilder builder = new SAXBuilder();
    final Document document = builder.build(originalFile);

    final XPathFactory xFactory = XPathFactory.instance();

    final String expression = String.format("//section[@label='%s']/section/section", LABEL);
    final XPathExpression<Element> sectionExpression = xFactory.compile(expression, Filters.element());
    final List<Element> sections = sectionExpression.evaluate(document);

Sections is empty.

Snippet of the XML

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://www.stellent.com/sitestudio/Project/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.stellent.com/sitestudio/Project/ http://www.stellent.com/sitestudio/ss_project_schema.xsd">
    <section label="Index">
        <section label="xyz">
           <section label="child">
           ...
           </section>
        </section>
    </section>
</project>

Removing the xmlns="http://www.stellent.com/sitestudio/Project/" works but isn't a solution!

Why isn't XPath able to know about this default namespace? Also, why does it care?

Better yet, how can I generically fix this?

Thank you for any insight.


回答1:


JDOM is doing the right thing. This is a FAQ, and not just for JDOM, but for XPath in general. The XPath specification is (somewhat) clear on this (I have bolded the relevant part):

A QName in the node test is expanded into an expanded-name using the namespace declarations from the expression context. This is the same way expansion is done for element type names in start and end-tags except that the default namespace declared with xmlns is not used: if the QName does not have a prefix, then the namespace URI is null (this is the same way attribute names are expanded). It is an error if the QName has a prefix for which there is no namespace declaration in the expression context.

From an XPath perspective, what this means is that the Namespace handling for rules in the XPath expression are not actually the same as the nodes in the XML. For all XPath expressions you need to define (duplicate) the namespace context for the expression, and the prefixes you use for the expression are actually completely independent to the ones used in the actual XML document.

You need to 'invent' a namespace prefix for your default namespace, and use that prefix in your expression (Here I have invented the namespace prefix ns):

final String expression = String.format("//ns:section[@label='%s']/ns:section/ns:section", LABEL);
final XPathExpression<Element> sectionExpression = xFactory.compile(expression, Filters.e, null,
         Namespace.getNamespace("ns", "http://www.stellent.com/sitestudio/Project/"))


来源:https://stackoverflow.com/questions/24573282/jdom2-with-xpath-doesnt-work-with-namespace

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