2009-12-31 32 views
7

Tôi có đoạn mã sau:Saxon XPath API trả về TinyElementImpl thay vì 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); 

và đây là kết quả ...

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

Chỉ cần làm rõ , nếu tôi làm điều này:

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

hoặc

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

tôi nhận được một ClassCastException

Làm thế nào mà có thể được? theo Suns Java 1.5 API NODE và nodeset nên bản đồ để org.w3c.dom.Nodeorg.w3c.dom.NodeList tương ứng

Chỉ cần clarify2 vâng tôi biết Node là một iterface, mà getClass() trả về một lớp bê tông.

Trả lời

6

Ok tôi đã tìm ra!

Nếu phương pháp đánh giá nhận được InputSource, lỗi trên xảy ra.

ví dụ:

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

Sau đó, kết quả là không thực hiện org.w3c.dom.Node (TinyElementImpl)

Nhưng nếu đánh giá nhận Node (hoặc một 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 

Nó hoạt động, nhưng vẫn còn, đây là kỳ lạ .. .

+0

Làm cho tinh thần .... nếu bạn đặt W3C DOM vào, bạn sẽ nhận được W3C DOM. Nếu không, bạn sẽ có được DOM độc quyền. – skaffman

+2

Chào mừng bạn đến với Java XML. – Esko

2

Node là giao diện. Bạn phải có một lớp cụ thể để thực hiện. Và getClass() trả về lớp bê tông đó.

Chỉnh sửa để trả lời nhận xét:

Xin lỗi, tôi không chú ý đến cá thể. Nhìn vào source code, có vẻ như TinyNodeImpl không thực hiện org.w3c.dom.Node. Và nhìn vào tài liệu JDK, có vẻ như nó không phải: tài liệu cho javax.xml.XPath đề cập đến bạn XPathConstants cho loại kết quả và nó đề cập đến "Loại dữ liệu NodeSet XPath 1.0" (nếu bạn nhìn vào thông số XPath 1.0, không được xác định).

Vì vậy, có vẻ như trả về từ API XPath chỉ bắt buộc phải nhất quán khi được sử dụng trong API đó. Không chính xác những gì bạn muốn nghe, tôi chắc chắn. Bạn có thể sử dụng cài đặt JDK tích hợp không? Tôi biết rằng nó trả về các đối tượng org.w3c.dom.

+0

Cảm ơn, tôi sẽ làm rõ câu hỏi. Và có, tôi nhận được một ClassCastException, bạn có thể nói rằng bởi 2 dòng cuối cùng của mã (đánh giá instanceof Node) nếu nó không phải là instanceof, nó không thực hiện giao diện đó, do đó một lớp diễn xuất ngoại trừ sẽ xảy ra. –

-1

kdgregory đúng là Node chỉ là một giao diện và TinyElementImpl triển khai giao diện đó. expression.evaluate() không thể trả lại phiên bản Node, nó phải trả lại lớp bê tông triển khai nút.

Nó có thể là hữu ích để chỉ ra rằng bạn có thể sử dụng một thể hiện của TinyElementImplnhư như Node, và bạn có thể dễ dàng đúc trường hợp của TinyElementImp-Node.

Ví dụ, điều này sẽ chỉ làm việc tốt:

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

Sau đó bạn có thể sử dụng result bằng cách gọi bất kỳ phương pháp của Node, và bằng cách đi qua nó để bất kỳ phương pháp mà chấp nhận một Node.

+0

Vui lòng đọc nhận xét về câu trả lời của kdgregory. TinyElementImpl không thực hiện Node bằng cách này. –

+0

OK, vâng, tôi thấy rằng tôi đã đưa ra giả định không chính xác. Tuy nhiên, tôi nghĩ tinh thần câu trả lời của tôi không giải quyết được một số khía cạnh của câu hỏi trong một nỗ lực trung thực để giúp đỡ. Tôi có thể sống với downvote mặc dù. –

2

Hơi kỳ quặc, cái này. Saxon javadoc nói rằng TinyElementImpl không triển khai bất kỳ giao diện nào trong số các giao diện org.w3c.dom và bạn sẽ nhận được chúng trở lại từ đánh giá XPath.

Đoán của tôi là Saxon tránh mô hình DOM chuẩn có lợi cho mô hình riêng của mình. Tôi nghi ngờ rằng số XPathConstants.NODE mà bạn chuyển đến evaluate thực sự chỉ là một gợi ý. Cho phép biểu thức XPath trả về bất kỳ thứ gì cũ (ví dụ: Apache JXPath sử dụng biểu thức XPath để truy vấn đồ thị đối tượng java), vì vậy nó được phép cho Saxon trả về các kiểu DOM của riêng nó thay vì org.w3c tiêu chuẩn.

Giải pháp: sử dụng các loại DOM Saxon như được trả lại hoặc không sử dụng Saxon.

3

Hãy thử mã này:

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

It in:

false 
true 

Đối tượng quay trở lại là loại NodeInfo, vì vậy bạn cần quấn nó như là một thực Node, vì vậy bạn có thể truy cập vào các phương pháp của nó:

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

Tính năng này hoạt động và là câu trả lời hữu ích nhất trên trang. Làm tốt! –

Các vấn đề liên quan