2011-11-08 32 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; 
} 

再見, 瓦萊里奧