使用xpath和jdom选择节点

时间:2013-05-01 09:00:19

标签: java xml xpath jdom javarosa

我有一个xform文档

<?xml version="1.0" encoding="UTF-8"?><h:html xmlns:h="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jr="http://openrosa.org/javarosa">
<h:head>
    <h:title>Summary</h:title>
    <model>
        <instance>
            <data vaultType="nsp_inspection.4.1">
                <metadata vaultType="metadata.1.1">
                    <form_start_time type="dateTime" />
                    <form_end_time type="dateTime" />
                    <device_id type="string" />
                    <username type="string" />
                </metadata>
                <date type="date" />
                <monitor type="string" />
            </data>
        </instance>
    </model>
</h:head>

我想使用xpath和jdom

从xform中选择数据元素
XPath xpath = XPath.newInstance("h:html/h:head/h:title/");

似乎工作正常,并选择标题元素,但

XPath xpath = XPath.newInstance("h:html/h:head/model");

不选择模型元素。 我想这与命名空间有关。

1 个答案:

答案 0 :(得分:7)

一些事情。你真的应该使用JDOM 2.0.x ...(2.0.5是最新版本)。 2.0.x版本中的XPath API远远优于JDOM 1.x中的XPath:请参阅https://github.com/hunterhacker/jdom/wiki/JDOM2-Feature-XPath-Upgrade

@wds对于xforms元素没有正确的命名空间是正确的....这就是XPath工作的原因,因为它具有相同的命名空间,与xhtml元素一起使用'h'前缀。您的代码可能会被破坏。

XPath中的命名空间经常让人感到困惑,因为 XPath 中的每个命名空间都有具有前缀。即使某些东西是XML中的默认命名空间(没有像'model'元素那样的前缀),它还有在XPath中有一个。 XPath中没有前缀的查询总是引用'no namespace'命名空间....(XPath规范:http://www.w3.org/TR/xpath/#node-tests

  

使用命名空间将节点测试中的QName扩展为扩展名   表达式上下文中的声明。这与扩展完成的方式相同   对于start和end-tags中的元素类型名称,除了默认名称空间   不使用xmlns声明:如果QName没有前缀,则使用   namespace URI为null(这与扩展属性名称的方式相同)。它是   如果QName具有没有名称空间声明的前缀,则会出错   表达式上下文

假设@wds是正确的,并且模型元素的命名空间应该是“http://www.w3.org/2002/xforms”,那么文档中的命名空间扩展应该是xmlns =“http://www.w3.org/2002 / XForms的”。但是,此命名空间是“默认”命名空间,XPath查询中无前缀命名空间的URI是“”。

要访问XPath中的http://www.w3.org/2002/xforms命名空间,必须为XPath的上下文指定一个前缀,例如xpns(对于xpath命名空间)。在JDOM 1.x中,您可以使用以下命令添加该命名空间:

XPath xpath = XPath.newInstance("/h:html/h:head/xpns:model");
xpath.addNamespace(Namespace.getNamespace("xpns", "http://www.w3.org/2002/xforms");
Element model = (Element)xpath.selectSingleNode(mydoc)

请注意如何将xpns添加到查询中。另请注意,我已将h:/ html引用“锚定”到文档的“/”根,这将提高查询评估的性能。

在JDOM 2.x中,XPath API更好(尽管在某些情况下它可能看起来有点过分)。

XPathFactory xpf = XPathFactory.instance();
XPathExpression<Element> xpath = xpf.compile("/h:html/h:head/xpns:model",
              Filters.element(), null,
              Namespace.getNamesace("xpns", "http://www.w3.org/2002/xforms"));
Element model = xpath.evaluateFirst(mydoc);

在JDOM 2.x javadoc中查看有关新XPath API的更多信息:XPathFactory.compile(...) javadoc