【问题标题】:getNodeName matches an XML node, but XPath can't find itgetNodeName 匹配一个 XML 节点,但 XPath 找不到它
【发布时间】:2013-01-11 16:12:50
【问题描述】:

这感觉像个菜鸟问题。

我正在查看一堆操作 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),并带有一条评论说“不要这样做,否则一切都会中断”。)

【问题讨论】:

    标签: java xpath


    【解决方案1】:

    如果您在没有命名空间的情况下进行解析,那么您应该将 somePrefix 留在表达式之外:

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

    这样做的原因是 XPath 对命名空间和本地名称执行匹配,不是限定名称(这是 getNodeName() 返回的内容)。如果您在 XPath 表达式中添加前缀,XPath 解释器将使用它从其名称空间映射中检索名称空间。因为你没有给它任何映射,所以它会失败。

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

    【讨论】:

    • 啊哈!没有意识到 XPath,感谢您的澄清!
    猜你喜欢
    • 1970-01-01
    • 2021-10-23
    • 2018-04-18
    • 1970-01-01
    • 2013-03-27
    • 2012-09-30
    • 2020-09-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多