在XML上应用xpath,其中名称空间与带有XOM的子项一起使用

时间:2013-02-18 10:31:51

标签: java xml-namespaces xom

我正在使用XOM库来解析xmls。我有以下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.

我可以理解,因为我只是通过Root Element创建名称空间上下文,所以它没有得到它的子名称空间。因此,一个解决方法可能是遍历所有子节点并收集其名称空间并将其添加到XpathContext对象中。但我的xml可以是10到20k行。所以我担心遍历方法会有多高效。

期待任何更好的建议

2 个答案:

答案 0 :(得分: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表达式中使用相同的前缀。

答案 1 :(得分:0)

据推测,您知道与每个元素名称关联的命名空间。所以你可以写:

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']";

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