getNodeName与XML节点匹配,但XPath无法找到它

时间:2013-01-11 16:12:51

标签: java xpath

这感觉就像是一个noob问题。

我正在查看一堆操纵XML DOM的Java代码。 (这些类是库存org.w3c.dom.Documentjavax.xml.xpath.XPath,并且与JDK 7一起发货。)它有大量的地方看起来像这样:

String expr = "/fixed/path/through/the/hierarchy";

// actual code reuses factory instances, etc
XPath xpath = XPathFactory.newInstance().newXPath();
Node topNode = someDocumentInstance.getFirstChild();
Node node = (Node) xpath.evaluate (expr, topNode, XPathConstants.NODE);

NodeList children = node.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
    Node child = children.item(i);
    if (child.getNodeName().equalsIgnoreCase("somePrefix:someTag")) {
        // "return child;" or otherwise break out of the loop
    }
}

一切正常。但这种循环似乎是一项乏味的工作;如果我们已经使用XPath来获取节点,那么为什么要迭代该节点的子节点来寻找已知的标签呢?

所以我尝试重写一个部分来直接获取子节点。但是查询使用

String expr = "/fixed/path/through/the/hierarchy/somePrefix:someTag";

永远不会匹配任何东西。我尝试过请求XPathConstants.NODESET.STRING等变体,但仍然没有结果。 (无论如何,应该只有这些节点中的一个。)

我觉得我在这里遗漏了一些非常明显的东西,但我无法弄清楚为什么完整的查询失败,当查询为父母加上手动循环通过子项时。当我使用像这样的查询时,XPath是否测试了getNodeName()以上节点的某些质量?

我提出的唯一理论是它与XML命名空间有关,这些命名空间在本项目中没有使用。 (实际上在DocumentBuilderFactory实例上调用了.setNamespaceAware(false),并发表了一条评论说“请关闭它或者所有地方都会中断”。)

1 个答案:

答案 0 :(得分:1)

如果您在没有名称空间的情况下进行解析,那么您应该将somePrefix从表达式中删除:

String expr = "/fixed/path/through/the/hierarchy/someTag";

原因是XPath在命名空间和本地名称上执行匹配,不是限定名称(这是getNodeName()返回的内容)。如果在XPath表达式中放置前缀,XPath解释器将使用它从命名空间映射中检索命名空间。既然你没有给它任何映射,那就会失败。

此外,如果您要遍历子节点,则可能需要使用NODESET