撒克逊人和XPath。无法理解

时间:2017-09-07 10:39:32

标签: xml xpath saxon

我有一种测试方法

    private String getXmlVersion(byte[] xml) throws Exception {
        String expression = "//Document/@version";
        XPathFactoryImpl xPathFactory = new XPathFactoryImpl();
        XPath xPath = xPathFactory.newXPath();
//        DocumentBuilder db = new DocumentBuilderFactoryImpl().newDocumentBuilder();
//        org.w3c.dom.Document xmlDoc = db.parse(new ByteArrayInputStream(xml));
        XPathExpression ex = xPath.compile(expression);
//        return  "" + ex.evaluate(xmlDoc, XPathConstants.STRING);
        return  "" + ex.evaluate(new InputSource(new ByteArrayInputStream(xml)), XPathConstants.STRING);
    }

我正在使用net.sf.saxon.dom.DocumentBuilderFactoryImplnet.sf.saxon.xpath.XPathFactoryImpl。此版本未通过测试,cos XPath评估为空字符串。但是,如果我取消注释行并开始使用DocumentBuilder - XPath按预期进行评估,并且所有测试都将通过。

documentation我读到了......

  

重要的是要注意编译的XPath表达式只能是   与使用相同Saxon构建的源文档一起使用   配置。

似乎当我同时使用DocumentBuilderFactoryImplXPathFactoryImpl时,他们的Configuration不同,但测试通过了。但是,当我只使用XpathFactoryImpl时会出现什么问题?

我使用的是撒克逊9.2.0.5。

任何人都可以通过使用Saxon和XPath的正确方法帮助我吗? 感谢您浪费时间和我的问候。

修改 我试图使用s9api,这是一个方法示例

private String getVersion(byte[] xmlData) throws Exception {
    Processor proc = new Processor(false);
    DocumentBuilder builder = proc.newDocumentBuilder();
    XPathCompiler xpc = proc.newXPathCompiler();
    xpc.declareNamespace("", "http://namespaceurl.info/ver2/rev2");

    XPathSelector selector = xpc.compile("//Document/@version").load();
    selector.setContextItem(builder.build(new StreamSource(new ByteArrayInputStream(xmlData))));
    XdmItem xdmItem = selector.evaluateSingle();
    return xdmItem == null ? "" : xdmItem.getStringValue();
}

此方法传递了一半的测试,因为它使用了明确定义的命名空间。但是在不同版本的文档中,命名空间是不同的。

1 个答案:

答案 0 :(得分:1)

使用Saxon和XPath的最佳方法是使用Saxon的s9api API而不是JAXP API。这有几个好处:

(a)JAXP API是围绕XPath 1.0设计的,而不是2.0 / 3.1

(b)JAXP API虽然试图成为对象模型中立的,但它是围绕DOM设计的,而对于Saxon来说,DOM可能是所有受支持的树中最低效的树模型。

(c)s9api更有用(类型安全,线程安全,命名空间绑定,外部变量和函数的绑定)。

如果您确实希望将JAXP XPath API与Saxon一起使用,并针对DOM树运行它,那么就可以完成它。

您还没有说过您使用的撒克逊版本。 DocumentBuilderFactoryImpl在9.3中已弃用,并在9.6之前(当前版本为9.8)下降了一段时间。

在这个阶段,它取决于你想做什么。您想对源树运行几个XPath表达式,还是只运行一个?如果它只是一个,你可以提供一个StreamSource,让Saxon以它认为最有效的方式构建树。如果它是几个,那么你应该自己构建树。它是否必须是一个DOM树,因为DOM的效率远低于其他模型(特别是撒克逊自己的TinyTree)。如果是,那么您可以简单地为XPath评估提供DOMSource。如果没有,那么构建一个TinyTree - 此时你最好使用s9api接口而不是JAXP。