2009-12-31 54 views
7
TinyElementImpl

我有以下代碼:撒克遜的XPath API返回,而不是org.w3c.dom.Node中

// xpath evaluates to net.sf.saxon.xpath.XPathEvaluator 
XPath xpath = XPathFactory.newInstance().newXPath(); 
XPathExpression expression = xpath.compile("/foo/bar"); 
Object evaluate = expression.evaluate(someXML, XPathConstants.NODE); 
Object evaluate2 = expression.evaluate(someXML, XPathConstants.NODESET); 

System.out.println(evaluate!=null?evaluate.getClass():"null"); 
System.out.println(evaluate2!=null?evaluate2.getClass():"null2"); 

System.out.println(evaluate instanceof Node); 
System.out.println(evaluate2 instanceof NodeList); 

,這是結果...

 
class net.sf.saxon.tinytree.TinyElementImpl 
class java.util.ArrayList 
false 
false 

只是爲了澄清如果我這樣做:

org.w3c.dom.Node node = (org.w3c.dom.Node)evaluate; 

org.w3c.dom.NodeList node = (org.w3c.dom.NodeList)evaluate2; 

我得到了ClassCastException

怎麼可能?根據太陽的Java 1.5 API節點NODESET應該映射到org.w3c.dom.Nodeorg.w3c.dom.NodeList分別

只是爲了clarify2是的,我知道Node是一個iterface,是的getClass()返回一個具體的類。

回答

6

好吧我想通了!

如果評估方法收到InputSource,則會發生上述錯誤。

例如

InputSource someXML = new InputSource(new StringReader("<someXML>...</someXML>)"); 
Object result = expression.evaluate(someXML, XPathConstants.NODE); 
Node node = (Node) result; // ClassCastException 

然後導致不執行org.w3c.dom.NodeTinyElementImpl

但是如果評估收到Node(或Document):

DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); 
DocumentBuilder documentBuilder = builderFactory.newDocumentBuilder(); 
Document someXML = documentBuilder.parse(new InputSource(new StringReader("<someXML>...</someXML>)")); 
Object result = expression.evaluate(someXML, XPathConstants.NODE); 
Node node = (Node) result; // works 

它的工作原理,不過,這是奇怪.. 。

+0

有意義....如果你放入W3C DOM,你會得到W3C DOM。否則,你會獲得專有的DOM。 – skaffman 2010-01-02 17:46:10

+2

歡迎使用Java XML。 – Esko 2010-01-02 17:50:25

2

Node是一個接口。你必須有一個具體的實施類。 getClass()返回具體的類。

編輯迴應評論:

對不起,我沒有注意的instanceof。看着source code,看起來TinyNodeImpl沒有實現org.w3c.dom.Node。並且查看JDK文檔,看起來並不需要:javax.xml.XPath的doc針對結果類型指向XPathConstants,它指向「XPath 1.0 NodeSet數據類型」(如果您查看XPath 1.0規範沒有定義)。

因此,似乎來自XPath API的回報只需在該API中使用時保持一致。不完全是你想聽到的,我敢肯定。你可以使用內置的JDK實現嗎?我知道它返回org.w3c.dom對象。

+0

謝謝,我我會澄清這個問題。是的,我得到一個ClassCastException,你可以通過代碼的最後2行(evaluate instanceof Node)來判斷它是否不是instanceof,它不會實現這個接口,因此會產生一個類型轉換exceptino。 – 2009-12-31 14:13:37

-1

kdgregory是正確的,Node只是一個接口,而TinyElementImpl實現該接口。 expression.evaluate()不能返回Node的實例,它必須返回一個具體類,其中實現了節點。

這可能是要指出,你可以使用的TinyElementImpl實例作爲Node有用,您可以輕鬆地投TinyElementImp實例Node

例如,這應該只是罰款:

Node result = (Node) expression.evaluate(someXML, XPathConstants.NODE); 

然後,您可以通過調用任何的Node的方法,並把它傳遞給它接受一個Node任何方法使用result

+0

請閱讀對kdgregory的回答的評論。 TinyElementImpl不會實現Node。 – 2009-12-31 14:27:28

+0

好的,是的,我看到我做了一個錯誤的假設。 儘管如此,我認爲我的回答的精神確實解決了問題的某些方面,並且誠實地致力於提供幫助。 雖然我可以忍受downvote。 – 2009-12-31 16:29:59

2

這個有點奇怪。 Saxon javadoc表示TinyElementImpl未實現org.w3c.dom接口中的任何一個,但您可以從XPath評估中找回它們。

我的猜測是,撒克遜人避開了標準的DOM模型而偏愛自己的模型。我懷疑你傳遞給evaluateXPathConstants.NODE實際上只是一個提示。允許XPath表達式返回任何舊事物(例如,Apache JXPath使用XPath表達式來查詢Java對象圖),因此允許Saxon返回它自己的DOM類型,而不是標準org.w3c

解決方案:使用返回的撒克遜DOM類型,或者不使用撒克遜。

3

試試此代碼:

Object evaluate = expression.evaluate(someXML, XPathConstants.NODE); 
System.out.println(evaluate instanceof Node); 
System.out.println(NodeOverNodeInfo.wrap((NodeInfo) evaluate) instanceof Node); 

它打印:

false 
true 

返回的對象是NodeInfo型的,所以你需要把它包裝成一個真正的Node,這樣你就可以訪問它的方法:

Node n = NodeOverNodeInfo.wrap((NodeInfo) evaluate); 
System.out.println(n.getNodeName()); 
System.out.println(n.getTextContent()); 
+0

這是有效的,並且是頁面上最有幫助的答案。做得好! – 2016-02-05 15:44:07