如何在Java中使用Saxon XPath 2.0?

时间:2015-09-22 12:27:04

标签: java xpath saxon

我喜欢在xPath中使用正则表达式,所以我安装了Saxon9.6

  1. 我的$ {java.home}是C:\ Program Files \ Java \ jdk1.7.0_51。
  2. 我在C:\ Program中提取了saxonHE9-6-0-6J.zip 文件\爪哇\ jdk1.7.0_51 \ JRE \ lib中\分机
  3. 并将saxonhe9.jar添加到我的classpath变量中。
  4. 然后我在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

  5. 但现在我无法找到this页面上描述的示例。

4 个答案:

答案 0 :(得分:8)

在Saxon的最新版本中,JAR文件不再包含将其作为JAXP XPath工厂提供程序宣传的meta-inf服务文件。这是因为太多的应用程序遇到了问题:如果应用程序是经过编写和测试的,可以使用JDK附带的XPath 1.0引擎,那么如果你尝试使用Saxon的XPath 2.0引擎运行它,它很有可能会失败,这种情况的发生仅仅是撒克逊人在阶级路径上的结果。因此,如果您想使用Saxon作为XPath引擎,则现在必须明确请求,例如通过直接实例化net.sf.saxon.xpath.XPathFactoryImpl

我的意思是调用new XPathFactoryImpl()而不是XPathFactoryImpl.newInstance(),因为它是从XPathFactory继承的。

但是,因为XPath 2.0类型系统比XPath 1.0更丰富,所以JAXP界面非常笨拙,我建议改为using the s9api interface

答案 1 :(得分:3)

我像这样使用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');
    }
}

答案 2 :(得分:1)

使用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语句。

答案 3 :(得分:-3)

(虽然这是目前接受的答案,Michael Kay's answer below中有一条重要的信息,我认为这是对这个问题更好的答案,但我不能更改接受的答案标志......)

使用Saxon在Java中设置转换非常容易,只需参考the documentation here即可。另一个straightforward how-to can be found here。其他例子遍布网络。

XPath API for Java is documented here at Saxonica

注意,您的链接引用了7.7版。您下载的是9.6版。如果要使用7.7中的示例,则应该下载该版本。它们可能仍然有些准确,但我不确定。