我有一种测试方法
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.DocumentBuilderFactoryImpl
和net.sf.saxon.xpath.XPathFactoryImpl
。此版本未通过测试,cos XPath评估为空字符串。但是,如果我取消注释行并开始使用DocumentBuilder
- XPath按预期进行评估,并且所有测试都将通过。
在documentation我读到了......
重要的是要注意编译的XPath表达式只能是 与使用相同Saxon构建的源文档一起使用 配置。
似乎当我同时使用DocumentBuilderFactoryImpl
和XPathFactoryImpl
时,他们的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();
}
此方法传递了一半的测试,因为它使用了明确定义的命名空间。但是在不同版本的文档中,命名空间是不同的。
答案 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。