无法使XPath与复杂的命名空间一起使用

时间:2014-10-10 10:35:01

标签: java xml xpath xml-namespaces

让我们从像这样的XML开始:

<?xml version="1.0" encoding="UTF-8"?>
<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/" timeStamp="2009-11-26T15:21:36Z" uuid="02334fb6-3ae8-4094-9279-29ff59fc5bc8">
    <config xmlns="http://www.xfa.org/schema/xci/2.6/">
        ...
    </config>
    <template xmlns="http://www.xfa.org/schema/xfa-template/2.6/">
        <subform name="movie" w="196.85mm">
            <field name="duration" y="11.7mm" x="2.175mm" w="62mm" h="9mm">
                ...
            </field>
            <field name="imdb" y="11.7mm" x="65.675mm" w="62mm" h="9mm">
                ...
            </field>
            ...
            <subform name="directors" layout="tb" x="2.175mm" y="30.75mm" w="95.25mm">
                ...
                <field name="director" w="91.075mm" h="9mm">
                    ...
                </field>
                ...
            </subform>
            ...
        </subform>
        ...
    </template>
    ...
</xdp:xdp>

(对于那些想知道的人,它是this iText example中使用的PDF的XFA文档的简化版本。)

现在我希望获得<field>中的所有NodeList元素,而XPath将非常适合此目的:

XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(new NamespaceContext() {
    public String getNamespaceURI(String p) {
        return "http://www.xfa.org/schema/xfa-template/2.6/";
    }
    public String getPrefix(String arg0) {return null;}
    public Iterator<?> getPrefixes(String arg0) {return null;}    
});
NodeList fields = (NodeList)xpath.evaluate("//field", document, XPathConstants.NODESET);

现在不起作用,结果是空的。我已尝试在null中返回getNamespaceURI;如果前缀为"http://ns.adobe.com/xdp/",则返回"xdp",否则返回null

我还尝试手动获取<template>元素并使用该节点的评估,上面的NamespaceContextgetNamespaceURI返回null ...

这个过于复杂的系统似乎没什么用处,我不想继续尝试而不弄清楚我做错了什么。

1 个答案:

答案 0 :(得分:1)

您应该在路径中使用前缀,例如//df:field然后当然要确保前缀绑定到名称空间URI,例如

xpath.setNamespaceContext(new NamespaceContext() {
    public String getNamespaceURI(String p) {
      if (p.equals("df")) {
        return "http://www.xfa.org/schema/xfa-template/2.6/";
      }
    }
    public String getPrefix(String arg0) {return null;}
    public Iterator<?> getPrefixes(String arg0) {return null;}    
});