I have XML String like this
我有这样的XML字符串
<resp><status>good</status><msg>hi</msg></resp>
I follow this help
我遵循这个帮助
Simplest way to query XML in Java
用Java查询XML的最简单方法
MyCode:
MyCode:
public static void main(String args[]) {
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));
String status = "";
String msg = "";
try {
status = (String) xpath.evaluate("/resp/status", source,XPathConstants.STRING);
msg = (String) xpath.evaluate("/resp/msg", source,XPathConstants.STRING);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("status=" + status);
System.out.println("Message=" + msg);
}
I want to get msg node value but i got exception
我想要获取msg节点值,但我得到了异常
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
I am not going to use some external library for this simple task. please guide me how to get other node's values. Thanks
对于这个简单的任务,我不打算使用外部库。请指导我如何获取其他节点的值。谢谢
3 个解决方案
#1
41
You can't reuse the same InputSource
for multiple evaluate()
invocations because it's automatically closed. Hence you're getting the Stream closed
IO exception. Try this
对于多个evaluate()调用,不能重用相同的InputSource,因为它是自动关闭的。因此,您得到的流关闭IO异常。试试这个
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:
A better approach would be to use a DocumentBuilderFactory
to parse your XML and build a Document
first (using JAXP's DOM APIs) which can then be reused across several XPath evaluations.
编辑:更好的方法是使用DocumentBuilderFactory来解析XML并首先构建文档(使用JAXP的DOM api),然后可以在多个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);
#2
12
Ravi's solution can also be expressed as:
Ravi的解也可以表示为:
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);
#3
6
You can try jcabi-xml
, which does DOM manipulations behind the scene:
您可以尝试jcab -xml,它在后台执行DOM操作:
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);
#1
41
You can't reuse the same InputSource
for multiple evaluate()
invocations because it's automatically closed. Hence you're getting the Stream closed
IO exception. Try this
对于多个evaluate()调用,不能重用相同的InputSource,因为它是自动关闭的。因此,您得到的流关闭IO异常。试试这个
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:
A better approach would be to use a DocumentBuilderFactory
to parse your XML and build a Document
first (using JAXP's DOM APIs) which can then be reused across several XPath evaluations.
编辑:更好的方法是使用DocumentBuilderFactory来解析XML并首先构建文档(使用JAXP的DOM api),然后可以在多个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);
#2
12
Ravi's solution can also be expressed as:
Ravi的解也可以表示为:
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);
#3
6
You can try jcabi-xml
, which does DOM manipulations behind the scene:
您可以尝试jcab -xml,它在后台执行DOM操作:
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);