2011-11-08 33 views
2

我想使用撒克逊运行“不同值”的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) 在sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

撒克逊-DOM jar文件是在类路径。 另外,如果我尝试调用“不同的值”直接在文档对象,我得到一个:

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在net.sf.saxon.dom.DOMObjectModel处使用$ 000(DOMObjectModel.java:42) $ 5.convert(DOMObjectModel.java:166) at net.sf.saxon.xpath.XPathExpressionImpl.evaluate(XPathExpressionImpl.java:352) 在net.sf.saxon.xpath.XPathEvaluator.evaluate(XPathEvaluator.java:434)

我想不通这里发生了什么。而谷歌也不是!

回答

4

首先要说明的是,DOM和撒克逊人并没有特别合作。如果您正在构建树以便使用Saxon,则优先使用Saxon的本地树模型 - 它比DOM快十倍。

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

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

+0

@arash:要查看代码示例,一个使用Saxon的原生树和一个使用DOM ,转到http://sourceforge.net/projects/saxon/files/Saxon-HE/9.4/然后下载撒克逊资源文件。查看XPathExample.java和XPathExampleDOM.java的“samples/java”文件夹。这些样本有助于查看差异。 –

0

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

<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); 

     } 

这是什么意思是由撒克逊的树模型? 唯一的问题是评估方法返回List而不是NodeList。 我想提一提的是,由于速度和功能都非常出色,我们转移到了Saxon,所以代码库对JAXP API有很多依赖关系,这是一个很好的选择。

+0

您在Maven存储库中找到的任何Saxon版本都是非官方且未经授权的,它可能不包含第三方组件(如Unicode库)的许可条款所要求的法定通知。目前版本的Saxon是9.4。是的,NodeInfo是撒克逊树模型中的一个节点。 NodeList类特定于DOM,如果您正在处理DOM,则只会返回NodeList。 (恐怕处理DOM以外的模型时JAXP规范非常混乱,我会优先推荐Saxon的s9api API。) –

1

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

getTagValue( “COMMODITYNAME”,NodeOverNodeInfo.wrap((的nodeinfo)s.get(I))) “COMMODITYNAME” 是在节点您想要读取XML的值,并且NodeOverNodeInfo.wrap((NodeInfo)s.get(i))是当前从“s”列表指向的节点。

私人字符串getTagValue(字符串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; 
} 

再见, 瓦莱里奥