1

我将JavaSaxon 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()仅获取第一个值(人):

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

...如果我尝试将其转换为 a ,则代码会在运行时中断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()orgetNodeValue()的调用

4

1 回答 1

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 的本机模型比任何外部模型都快得多。

于 2013-06-26T10:57:41.307 回答