获取一系列元素标签的XPath(Java / Saxon)

时间:2013-06-26 09:31:39

标签: java xpath saxon xpath-2.0

我正在使用 Java Saxon HE 9.4 ,因此我可以获得 XPath 2.0 支持。

给出以下XML实例文档:

<entities>
    <entity>
        <person>
            James
        </person>
    </entity>
    <entity>
        <legalEntity>
            ACME
        </legalEntity>
    </entity>
</entities>

我知道我可以通过执行以下操作获取实体元素标记的列表:

XPathExpression expr = xpath.compile("/entities/entity/*");
NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
for (int i = 0 ; i < nodes.getLength() ; i++)
    System.out.println("element name = "+ nodes.item(i).getNodeName());

以上将输出:

element name = person
element name = legalEntity

......正如所料。

但是,逻辑分布在两个地方:XPath表达式本身和对getNodeName方法的调用。我想要的是一个XPath表达式,它将返回一个通用的结果列表,我可以通过调用一些泛型方法(而不是getNodeName)来迭代它。

这样,所有逻辑都可以驻留在XPath表达式本身中,我的代码可以将XPath字符串保存在文件中,并在运行时处理它们以获取结果列表。

尝试XPAth表达式/entities/entity/*/name()仅获取第一个值(person):

XPathExpression expr = xpath.compile("/entities/entity/*/name()");
System.out.println("element name = "+expr.evaluate(doc));

...如果我尝试将其转换为NodeList

,代码会在运行时中断
XPathExpression expr = xpath.compile("/entities/entity/*/name()");
NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
for (int i = 0 ; i < nodes.getLength() ; i++) {
    ...

(以上内容失败:net.sf.saxon.trans.XPathException: Cannot convert XPath value to Java object: required class is org.w3c.dom.NodeList; supplied value has type xs:string

有没有一种通用的方法可以将 XPath 表达式计算到结果列表(可以是元素标签,元素值,属性值和标签等),以便代码迭代这些结果在所有情况下都相同,并且不必区分对getNodeName()getNodeValue()的调用?

1 个答案:

答案 0 :(得分:2)

您正在使用XPath的JAXP接口。这是为XPath 1.0设计的,只能识别XPath 1.0数据类型(字符串,节点集等)。您想要执行返回字符串列表(或可能是QNames)的查询,因此您需要使用支持此类数据类型的API - 具体而言,您需要转移到Saxon的s9api API。

在s9api接口中,XPathSelector对象(参见http://www.saxonica.com/documentation/#!javadoc/net.sf.saxon.s9api/XPathSelector)实现了Java的Iterable接口,因此您可以直接在Java“for-each”指令中使用它来将结果作为一系列XdmItem对象处理; XdmItems可以是节点或原子值,实际上是XPath 2.0数据模型中定义的任何类型。

您可以使用s9api针对Saxon的本机树模型(使用s9api DocumentBuilder构建)或针对外部模型(如DOM,JDOM,XOM等)运行XPath表达式。使用Saxon的本机模型比任何外部模型都快得多