如何在 Java 中使用 Saxon XPath 2.0?
How to use Saxon XPath 2.0 with Java?
我喜欢在xPath中使用正则表达式,所以安装了Saxon9.6
- 我的 ${java.home} 是 C:\Program Files\Java\jdk1.7.0_51.
- 我在 C:\Program 中提取了 saxonHE9-6-0-6J.zip
Files\Java\jdk1.7.0_51\jre\lib\ext
- 并将 saxonhe9.jar 添加到我的类路径变量中。
然后我在C:\Program下创建了一个jaxp.properties文件
Files\Java\jdk1.7.0_51\jre\lib 并添加以下行:
javax.xml.transform.TransformerFactory = net.sf.saxon.TransformerFactoryImpl
javax.xml.xpath.XPathFactory","net.sf.saxon.xpath.XPathFactoryImpl
但是现在我找不到像 this 页面上描述的例子。
(虽然这是目前公认的答案,但 中有一条重要信息,我认为这是对这个问题的更好答案,但是我无法更改已接受答案标志...)
使用 Saxon 在 Java 中设置转换非常容易,只需参考 the documentation here. Another straightforward how-to can be found here。其他例子遍布全网
XPath API for Java is documented here at Saxonica.
请注意,您的 link 引用的是 7.7 版。您下载了 9.6 版。如果您想使用 7.7 中的示例,您应该下载该版本。它们可能仍然有些准确,但我不确定。
在最新版本的 Saxon 中,JAR 文件不再包含将其宣传为 JAXP XPath 工厂提供程序的 meta-inf 服务文件。这是因为太多的应用程序有问题:如果应用程序被编写并测试为与 JDK 附带的 XPath 1.0 引擎一起工作,那么如果您尝试 运行,它很可能会失败它与 Saxon 的 XPath 2.0 引擎一起使用,而这仅仅是因为 Saxon 在 class 路径上。所以如果你想使用 Saxon 作为你的 XPath 引擎,你现在必须使请求明确,例如通过直接实例化 net.sf.saxon.xpath.XPathFactoryImpl
。
我的意思是调用 new XPathFactoryImpl()
而不是 XPathFactoryImpl.newInstance()
因为它继承自 XPathFactory
。
但是,由于 XPath 2.0 类型系统比 XPath 1.0 丰富得多,JAXP 界面确实很笨拙,我建议 using the s9api interface。
使用 S9API 从未像它应该的那样简单。这是我可以创建的最简单的工作示例。这是一个完整的单元测试,适用于 NetBeans 8 中的 Saxon 9.7 HE。
假设这个 XML (simple.xml):
<person>
<firstname>James</firstname>
<age>25</age>
</person>
运行 这个单元测试,正在寻找名字节点:
import java.io.File;
import java.util.Iterator;
import java.util.List;
import javax.xml.transform.sax.SAXSource;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import javax.xml.xpath.XPathFactoryConfigurationException;
import net.sf.saxon.Configuration;
import net.sf.saxon.lib.NamespaceConstant;
import net.sf.saxon.om.DocumentInfo;
import net.sf.saxon.om.NodeInfo;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.xpath.XPathFactoryImpl;
import org.junit.Test;
import org.xml.sax.InputSource;
import static org.junit.Assert.*;
public class xPath2
{
@Test
public void mytest() throws XPathFactoryConfigurationException, XPathException, XPathExpressionException
{
System.setProperty("javax.xml.xpath.XPathFactory:" + NamespaceConstant.OBJECT_MODEL_SAXON, "net.sf.saxon.xpath.XPathFactoryImpl");
XPathFactory xPathFactory = XPathFactory.newInstance(NamespaceConstant.OBJECT_MODEL_SAXON);
XPath xPath = xPathFactory.newXPath();
InputSource inputSource = new InputSource(new File("simple.xml").toURI().toString());
SAXSource saxSource = new SAXSource(inputSource);
Configuration config = ((XPathFactoryImpl) xPathFactory).getConfiguration();
DocumentInfo document = config.buildDocument(saxSource);
String xPathStatement = "//firstname";
XPathExpression xPathExpression = xPath.compile(xPathStatement);
List matches = (List) xPathExpression.evaluate(document, XPathConstants.NODESET);
if (matches != null)
{
for (Iterator iter = matches.iterator(); iter.hasNext();)
{
NodeInfo node = (NodeInfo) iter.next();
assertEquals("firstname", node.getDisplayName());
assertEquals("James", node.getStringValue());
}
}
}
}
这是 Saxon 9.7 资源 (http://www.saxonica.com/download/download_page.xml) 附带的示例之一的简化版本。
请注意,xPath 语句不是 xPath 2.0,但此代码可用于 2.0 语句。
我这样使用 Saxon-HE 9.8.0-5:
Processor processor = new Processor(false);
XdmNode xdm = processor.newDocumentBuilder().build(new StreamSource(new StringReader(xml)));
XdmValue result = processor.newXPathCompiler().evaluate(query, xdm);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < result.size(); i++) {
sb.append(result.itemAt(i).getStringValue());
if (i + 1 != result.size()) {
sb.append('\n');
}
}
我喜欢在xPath中使用正则表达式,所以安装了Saxon9.6
- 我的 ${java.home} 是 C:\Program Files\Java\jdk1.7.0_51.
- 我在 C:\Program 中提取了 saxonHE9-6-0-6J.zip Files\Java\jdk1.7.0_51\jre\lib\ext
- 并将 saxonhe9.jar 添加到我的类路径变量中。
然后我在C:\Program下创建了一个jaxp.properties文件 Files\Java\jdk1.7.0_51\jre\lib 并添加以下行:
javax.xml.transform.TransformerFactory = net.sf.saxon.TransformerFactoryImpl javax.xml.xpath.XPathFactory","net.sf.saxon.xpath.XPathFactoryImpl
但是现在我找不到像 this 页面上描述的例子。
(虽然这是目前公认的答案,但
使用 Saxon 在 Java 中设置转换非常容易,只需参考 the documentation here. Another straightforward how-to can be found here。其他例子遍布全网
XPath API for Java is documented here at Saxonica.
请注意,您的 link 引用的是 7.7 版。您下载了 9.6 版。如果您想使用 7.7 中的示例,您应该下载该版本。它们可能仍然有些准确,但我不确定。
在最新版本的 Saxon 中,JAR 文件不再包含将其宣传为 JAXP XPath 工厂提供程序的 meta-inf 服务文件。这是因为太多的应用程序有问题:如果应用程序被编写并测试为与 JDK 附带的 XPath 1.0 引擎一起工作,那么如果您尝试 运行,它很可能会失败它与 Saxon 的 XPath 2.0 引擎一起使用,而这仅仅是因为 Saxon 在 class 路径上。所以如果你想使用 Saxon 作为你的 XPath 引擎,你现在必须使请求明确,例如通过直接实例化 net.sf.saxon.xpath.XPathFactoryImpl
。
我的意思是调用 new XPathFactoryImpl()
而不是 XPathFactoryImpl.newInstance()
因为它继承自 XPathFactory
。
但是,由于 XPath 2.0 类型系统比 XPath 1.0 丰富得多,JAXP 界面确实很笨拙,我建议 using the s9api interface。
使用 S9API 从未像它应该的那样简单。这是我可以创建的最简单的工作示例。这是一个完整的单元测试,适用于 NetBeans 8 中的 Saxon 9.7 HE。
假设这个 XML (simple.xml):
<person>
<firstname>James</firstname>
<age>25</age>
</person>
运行 这个单元测试,正在寻找名字节点:
import java.io.File;
import java.util.Iterator;
import java.util.List;
import javax.xml.transform.sax.SAXSource;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import javax.xml.xpath.XPathFactoryConfigurationException;
import net.sf.saxon.Configuration;
import net.sf.saxon.lib.NamespaceConstant;
import net.sf.saxon.om.DocumentInfo;
import net.sf.saxon.om.NodeInfo;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.xpath.XPathFactoryImpl;
import org.junit.Test;
import org.xml.sax.InputSource;
import static org.junit.Assert.*;
public class xPath2
{
@Test
public void mytest() throws XPathFactoryConfigurationException, XPathException, XPathExpressionException
{
System.setProperty("javax.xml.xpath.XPathFactory:" + NamespaceConstant.OBJECT_MODEL_SAXON, "net.sf.saxon.xpath.XPathFactoryImpl");
XPathFactory xPathFactory = XPathFactory.newInstance(NamespaceConstant.OBJECT_MODEL_SAXON);
XPath xPath = xPathFactory.newXPath();
InputSource inputSource = new InputSource(new File("simple.xml").toURI().toString());
SAXSource saxSource = new SAXSource(inputSource);
Configuration config = ((XPathFactoryImpl) xPathFactory).getConfiguration();
DocumentInfo document = config.buildDocument(saxSource);
String xPathStatement = "//firstname";
XPathExpression xPathExpression = xPath.compile(xPathStatement);
List matches = (List) xPathExpression.evaluate(document, XPathConstants.NODESET);
if (matches != null)
{
for (Iterator iter = matches.iterator(); iter.hasNext();)
{
NodeInfo node = (NodeInfo) iter.next();
assertEquals("firstname", node.getDisplayName());
assertEquals("James", node.getStringValue());
}
}
}
}
这是 Saxon 9.7 资源 (http://www.saxonica.com/download/download_page.xml) 附带的示例之一的简化版本。
请注意,xPath 语句不是 xPath 2.0,但此代码可用于 2.0 语句。
我这样使用 Saxon-HE 9.8.0-5:
Processor processor = new Processor(false);
XdmNode xdm = processor.newDocumentBuilder().build(new StreamSource(new StringReader(xml)));
XdmValue result = processor.newXPathCompiler().evaluate(query, xdm);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < result.size(); i++) {
sb.append(result.itemAt(i).getStringValue());
if (i + 1 != result.size()) {
sb.append('\n');
}
}