【问题标题】:Applying xpath on XML where namespaces are with children with XOM在 XML 上应用 xpath,其中命名空间带有 XOM 的子级
【发布时间】:2013-02-02 18:11:56
【问题描述】:

我正在使用 XOM 库来解析 xml。我有以下 XML

<ns4:parent xmlns:ns4="http://sample.xml.com/ns4">
    <ns4:child1 xmlns:ns1="http://sample.xml.com/ns1" xmlns:xsi="http://sample.xml.com/xsi">
        <ns1:child2>divaStatus</ns1:child2>
        <xsi:child>something</xsi:child>
    </ns4:child1>
</ns4:parent>

我想应用像ns4:parent/ns4:child1/ns1:child2 这样的xpath。所以我的代码如下所示

Document doc = new Builder().build(inStream);  //inStream is containing the xml
XPathContext xc = XPathContext.makeNamespaceContext(doc.getRootElement());
doc.query("ns4:parent/ns4:child1/ns1:child2", xc);

我在这里收到XPathException

 Exception in thread "main" nu.xom.XPathException: XPath error: XPath expression uses unbound namespace prefix ns1.

我可以理解,由于我仅通过根元素创建命名空间上下文,因此它没有获取其子元素的命名空间。因此,一种解决方法可能是遍历所有孩子并收集他们的命名空间并将其添加到XpathContext 对象中。但我的 xml 可以是 10 到 20k 行。所以我担心遍历方法的效率会有多高。

期待更好的建议

【问题讨论】:

    标签: java xml-namespaces xom


    【解决方案1】:

    大概您知道与每个元素名称相关联的命名空间。所以你可以写:

    String xpath = "*[local-name()='parent' and namespace-uri()='http://sample.xml.com/ns4']"+
      "*[local-name()='child1' and namespace-uri()='http://sample.xml.com/ns2']"+
      "*[local-name()='child2' and namespace-uri()='http://sample.xml.com/ns1']";
    

    我希望它与前缀版本一样高效。

    【讨论】:

      【解决方案2】:

      这很容易(或者尽可能简单,考虑到 XPath 和 XML 命名空间的设计)。您只需要手动将要使用的任何命名空间添加到上下文中。例如,在这种情况下,

      XPathContext xc = new XPathContext();
      xc.addNamespace("ns4", "http://sample.xml.com/ns4");
      xc.addNamespace("ns1", "http://sample.xml.com/ns1");
      doc.query("ns4:parent/ns4:child1/ns1:child2", xc);
      

      请注意,您不必在文档使用的 XPath 表达式中使用相同的前缀。

      【讨论】:

      • :) 很高兴从库的直接开发人员那里得到一个问题的回复。为此非常感谢。是的,最终我们采用了这种方法来解决这个问题。我们在一个地方维护了所有可能的命名空间定义,并为这些定义准备了一个上下文,并使用该上下文来解析 xml。但如果 xml 引入任何新的命名空间,它将失败。所以它现在有点“不那么动态”。您对此有什么建议吗?
      • 我同意获得 Elliotte 的反馈。还有一个邮件列表 [xom-interest@lists.ibiblio.org],但我希望很多人先来这里,并且更容易重新访问答案。
      猜你喜欢
      • 2012-12-29
      • 2011-01-05
      • 1970-01-01
      • 1970-01-01
      • 2020-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-09
      相关资源
      最近更新 更多