2013-05-23 31 views
29

Tôi có chuỗi XML như thế nàyParse XML đơn giản Chuỗi sử dụng Java XPath

<resp><status>good</status><msg>hi</msg></resp> 

Tôi làm theo sự giúp đỡ này

Simplest way to query XML in Java

MyCode:

Tôi muốn nhận được msg giá trị nút nhưng tôi đã nhận ngoại lệ

java.io.IOException: Stream closed 
at java.io.StringReader.ensureOpen(StringReader.java:39) 
at java.io.StringReader.read(StringReader.java:73) 
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.load(XMLEntityScanner.java:1742) 
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.arrangeCapacity(XMLEntityScanner.java:1619) 
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.skipString(XMLEntityScanner.java:1657) 
at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:193) 
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:771) 
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737) 
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:107) 
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:225) 
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:283) 
at com.sun.org.apache.xpath.internal.jaxp.XPathImpl.evaluate(XPathImpl.java:468) 
at com.sun.org.apache.xpath.internal.jaxp.XPathImpl.evaluate(XPathImpl.java:515) 
at Parsing.main(Parsing.java:25)--------------- linked to ------------------ 
javax.xml.xpath.XPathExpressionException 
at com.sun.org.apache.xpath.internal.jaxp.XPathImpl.evaluate(XPathImpl.java:475) 
at com.sun.org.apache.xpath.internal.jaxp.XPathImpl.evaluate(XPathImpl.java:515) 
at Parsing.main(Parsing.java:25) 
Caused by: java.io.IOException: Stream closed 
at java.io.StringReader.ensureOpen(StringReader.java:39) 
at java.io.StringReader.read(StringReader.java:73) 
at  com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.load(XMLEntityScanner.java:1742) 
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.arrangeCapacity(XMLEntityScanner.java:1619) 
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.skipString(XMLEntityScanner.java:1657) 
at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:193) 
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:771) 
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737) 
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:107) 
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:225) 
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:283) 
at com.sun.org.apache.xpath.internal.jaxp.XPathImpl.evaluate(XPathImpl.java:468) 
... 2 more 

Tôi sẽ không sử dụng một số thư viện bên ngoài cho tác vụ đơn giản này. hãy hướng dẫn tôi cách lấy các giá trị của nút khác. Cảm ơn

+0

bài viết tất cả các phương pháp của bạn nếu bạn muốn được giúp đỡ .. –

+0

Đừng mong đợi nhận được nhiều trợ giúp bằng cách chỉ chia sẻ một dòng mã. –

Trả lời

38

Bạn không thể sử dụng lại cùng một InputSource cho nhiều yêu cầu evaluate() vì nó được tự động đóng. Do đó bạn nhận được ngoại lệ Stream closed IO. Hãy thử điều này

InputSource source1 = new InputSource(new StringReader(xml)); 
InputSource source2 = new InputSource(new StringReader(xml)); 

String msg = xpath.evaluate("/resp/msg", source); 
String status = xpath.evaluate("/resp/status", source2); 

System.out.println("msg=" + msg + ";" + "status=" + status); 

EDIT:
Một cách tiếp cận tốt hơn sẽ được sử dụng một DocumentBuilderFactory để phân tích XML của bạn và xây dựng một Document đầu tiên (sử dụng DOM API JAXP của) mà sau đó có thể được tái sử dụng trên một số đánh giá XPath .

String xml = "<resp><status>good</status><msg>hi</msg></resp>"; 

InputSource source = new InputSource(new StringReader(xml)); 

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
DocumentBuilder db = dbf.newDocumentBuilder(); 
Document document = db.parse(source); 

XPathFactory xpathFactory = XPathFactory.newInstance(); 
XPath xpath = xpathFactory.newXPath(); 

String msg = xpath.evaluate("/resp/msg", document); 
String status = xpath.evaluate("/resp/status", document); 

System.out.println("msg=" + msg + ";" + "status=" + status); 
+0

vì vậy nếu tôi có nhiều nút thì tôi phải tạo nguồn cho mỗi nút? có giải pháp nào tốt hơn không? –

+0

Sử dụng 'DocumentBuilderFactory' để xây dựng một' Tài liệu' (một phần của API JAXP DOM) có thể được sử dụng lại trên nhiều đánh giá Xpath. –

+0

Kiểm tra cập nhật. Đã thêm một số mã để giúp bạn bắt đầu. –

11

Ravi's solution cũng có thể được diễn tả như:

String xml = "<resp><status>good</status><msg>hi</msg></resp>"; 

XPathFactory xpathFactory = XPathFactory.newInstance(); 
XPath xpath = xpathFactory.newXPath(); 

InputSource source = new InputSource(new StringReader(xml)); 
Document doc = (Document) xpath.evaluate("/", source, XPathConstants.NODE); 
String status = xpath.evaluate("/resp/status", doc); 
String msg = xpath.evaluate("/resp/msg", doc); 

System.out.println("status=" + status); 
System.out.println("Message=" + msg); 
+2

không quan tâm, nếu chuỗi XML là tốt, ok là có anyway chỉ cần chọn từ đầu tiên trong chuỗi trước dấu phẩy? hoặc chỉ chọn từ sau dấu phẩy? –

+0

@brookman Không có hỗ trợ XPath của Java. Bạn có thể có với XPath 2 - xem API Saxon. – McDowell

6

Bạn có thể thử jcabi-xml, mà hiện thao tác DOM đằng sau những cảnh:

import com.jcabi.xml.XML; 
import com.jcabi.xml.XMLDocument; 
XML xml = new XMLDocument("<resp>...</resp>"); 
String status = xml.xpath("/resp/status/text()").get(0); 
+0

Thư viện này rất đẹp, nhưng những gì tôi không thích là nó mang lại cho mọi khía cạnh - mà tôi không nghĩ là thực sự cần thiết –

+0

Vâng, chúng tôi đang lên kế hoạch để loại bỏ điều đó rất sớm – yegor256

+0

sẽ rất tốt đẹp! bất kỳ RSS nào tôi có thể đăng ký để giữ cho bản thân mình luôn cập nhật? –

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