saxon distinct-values抛出异常

时间:2011-11-08 03:44:49

标签: java xpath saxon

我正在尝试使用Saxon运行“distinct-values”XPath。这是我的代码:

 @Test
public void testAttributeSelect() throws XPathFactoryConfigurationException {
     System.setProperty("javax.xml.xpath.XPathFactory:"
     + NamespaceConstant.OBJECT_MODEL_SAXON,
     "net.sf.saxon.xpath.XPathFactoryImpl");
      System.setProperty("javax.xml.parsers.DocumentBuilderFactory",
    "net.sf.saxon.dom.DocumentBuilderFactoryImpl");
      String xpathString = "distinct-values(//id)";
    DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();

    domFactory.setNamespaceAware(true);

    try {
        DocumentBuilder builder = domFactory.newDocumentBuilder();
        System.out.println(builder.getClass());
        Document doc =
       builder.parse(this.getClass().getResourceAsStream("parametrizedId_feed.xml"));
        System.out.println(doc.getClass());
        XPath xpath =
      XPathFactory.newInstance(NamespaceConstant.OBJECT_MODEL_SAXON).newXPath();

        NodeList s1 = (NodeList) 
        xpath.evaluate("/matches", doc, XPathConstants.NODESET);
       NodeList s = (NodeList) 
       xpath.evaluate(xpathString, s1 , XPathConstants.NODESET);

我得到了这个例外:

  

javax.xml.xpath.XPathExpressionException:无法找到类net.sf.saxon.dom.DOMNodeList的节点的对象模型实现       at net.sf.saxon.xpath.XPathExpressionImpl.evaluate(XPathExpressionImpl.java:300)       at net.sf.saxon.xpath.XPathEvaluator.evaluate(XPathEvaluator.java:434)       at ca.cbc.panacea.playground.TestXpath.testAttributeSelect(TestXpath.java:43)       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

Saxon-dom jar文件位于类路径中。 另外,如果我尝试直接在doc对象上调用'distinct-values',我会得到:

  

net.sf.saxon.trans.XPathException:扩展函数必需类org.w3c.dom.NodeList;无法转换类net.sf.saxon.value.UntypedAtomicValue的提供值       at net.sf.saxon.dom.DOMObjectModel.convertXPathValueToObject(DOMObjectModel.java:395)       at net.sf.saxon.dom.DOMObjectModel.access $ 000(DOMObjectModel.java:42)       at net.sf.saxon.dom.DOMObjectModel $ 5.convert(DOMObjectModel.java:166)       at net.sf.saxon.xpath.XPathExpressionImpl.evaluate(XPathExpressionImpl.java:352)       at net.sf.saxon.xpath.XPathEvaluator.evaluate(XPathEvaluator.java:434)

我无法弄清楚这里发生了什么。谷歌也没有!

3 个答案:

答案 0 :(得分:4)

首先要指出的是,DOM和Saxon并不是特别好。如果您正在构建树以便在其上使用Saxon,请使用Saxon的原生树模型而不是DOM - 它的速度要快十倍。

你提到saxon-dom.jar的事实意味着你必须使用相当旧版本的Saxon,可能是不再支持的版本。所以我的下一个建议是转到更新版本。

我注意到的另一件事是你要求XPath处理器使用Saxon对象模型,然后使用它来处理DOM对象模型。我不知道这是否可能起作用。 (如果你想确保加载Saxon而不是其他一些XPath引擎,例如因为你需要XPath 2.0,那么最好完全跳过JAXP工厂机制并直接实例化Saxon实现。)

答案 1 :(得分:1)

我找到了一个从Saxon中检索NodeList的解决方案。 执行语句后#34; List s =(List)xpath.evaluate(xpathString,doc1,XPathConstants.NODESET);"您可以使用以下代码从List中读取节点和节点值:

getTagValue(" COMMODITYNAME",NodeOverNodeInfo.wrap((NodeInfo)s.get(i))) " COMMODITYNAME"是您希望读取值的XML中的节点,NodeOverNodeInfo.wrap((NodeInfo)s.get(i))是当前指向的节点" s"列表。

private String getTagValue(String strag,NodeOverNodeInfo nodeInfo)     {

    NodeList nodeList = nodeInfo.getChildNodes(); //list of  XML node
    Node nodeValue = null;
    String strReturn = null;
    for (int iItem=0;iItem<nodeList.getLength();iItem++)
    {
        nodeValue = nodeList.item(iItem).getFirstChild();   
        if (nodeValue != null && strag.equalsIgnoreCase(nodeValue.getParentNode().getNodeName()))
        {
            strReturn = nodeValue.getNodeValue();
            //punta la tag index
            //System.out.println(nodeValue.getParentNode().getNodeName()); //this is the node name
            //System.out.println(nodeValue.getNodeValue()); // this is the node value
        }
    }
return strReturn;
}

再见 瓦莱里奥

答案 2 :(得分:0)

这不是答案,我只是想评论迈克尔的回应,但评论非常有限。 谢谢迈克尔的回应。 我的依赖关系如下:

<dependency>
        <groupId>net.sourceforge.saxon</groupId>
        <artifactId>saxon</artifactId>
        <version>9.1.0.8</version>
    </dependency>
    <dependency>
        <groupId>net.sourceforge.saxon</groupId>
        <artifactId>saxon</artifactId>
        <version>9.1.0.8</version>
        <classifier>xpath</classifier>
    </dependency>

    <dependency>
    <groupId>net.sourceforge.saxon</groupId>
        <artifactId>saxon</artifactId>
        <version>9.1.0.8</version>
        <classifier>dom</classifier>
    </dependency>

AFAIK这是maven回购中的最新版本。如果我错过了什么,请告诉我。 你对情况的解释非常好,除了我需要一个示例代码来弄清楚如何做到这一切。 我做了以下更改,并且有效!

InputSource is = new InputSource(this.getClass().getResourceAsStream("parametrizedId_feed.xml"));
         SAXSource ss = new SAXSource(is);

        XPath xpath =  XPathFactory.newInstance(NamespaceConstant.OBJECT_MODEL_SAXON).newXPath();
        NodeInfo doc1 = ((XPathEvaluator)xpath).setSource(ss);
        System.out.println("Loaded XPath Provider " + xpath.getClass().getName());

       List s = (List) xpath.evaluate(xpathString, doc1 , XPathConstants.NODESET);
        for(int i = 0 ; i<s.size(); i++){
            String n = (String) s.get(i);
            System.out.println(n);

        }

这是撒克逊人树模型的意思吗? 唯一的问题是evaluate方法返回List而不是NodeList。 我想提一下,由于速度极快,功能更好,我们搬到了Saxon,所以代码库对JAXP API有许多依赖,这是一个很难驾​​驭的地方。