如何使用JDOM以名称空间中立的方式解析XMLDocument

时间:2013-12-04 00:24:25

标签: xpath xml-parsing xml-namespaces dom4j

我正在尝试使用Dom4J解析文档。该文档来自各种提供程序,有时带有名称空间,有时没有。

例如:

<book>
   <author>john</author>
   <publisher>
     <name>John Q</name>
   </publisher>
</book>

<book xmlns="http://schemas.xml.com/XMLSchemaInstance">
   <author>john</author>
   <publisher>
     <name>John Q</name>
   </publisher>
</book>

<book xmlns:i="http://schemas.xml.com/XMLSchemaInstance">
   <i:author>john</i:author>
   <i:publisher>
     <i:name>John Q</i:name>
   </i:publisher>
</book>

我有一个XPath列表。我将文档解析为Document类,然后使用xpaths搜索它。

        Document doc = parseDocument(documentFile);
        List<String> XmlPaths = new List<String>();
        XmlPaths.add("book/author");
        XmlPaths.add("book/publisher/name");

        for (int i = 0; i < XmlPaths.size(); i++)
        {
            String searchPath = XmlPaths.get(i);

            Node currentNode = doc.selectSingleNode(searchPath);
            assert(currentNode != null);
        }

此代码不适用于最后一个文档,即使用名称空间前缀的文档。

我尝试过这些技巧,但似乎都没有。

1)将xpath中的最后一个元素更改为名称空间中性:

/book/:author
/book/[local-name()='author']
/[local-name()='book']/[local-name()='author']

所有这些都抛出异常,说XPATH格式不正确。

2)使用DocumentHelper.createXPath()创建名称空间uris到XPAth;

知道我做错了吗?

仅供参考我正在使用dom4j 1.5版

1 个答案:

答案 0 :(得分:2)

您的XPath不包含标记名称。您的案例中的一般语法是

/TAGNAMEPARENT[CONDITION_PARENT]/TAGNAMECHILD[CONDITION_CHILD]

重要的一点是标签名称是必需,而条件是可选。如果您不想指定标记名称,则使用*作为“任何标记”。可能会对大型XML文件产生性能影响,因为您始终必须迭代节点集而不是使用索引查找。也许@MichaelKay可以对此发表评论。

请改为尝试:

/*[local-name()='book']/*[local-name()='author']