Parse XML Simple String using Java XPath
77,653
Solution 1
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
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.
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);
Solution 2
Ravi's solution can also be expressed as:
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);
Solution 3
You can try jcabi-xml
, which does DOM manipulations behind the scene:
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);
![Waqas Ali](https://i.stack.imgur.com/tKLjZ.jpg?s=256&g=1)
Author by
Waqas Ali
Updated on February 19, 2020Comments
-
Waqas Ali over 4 years
I have XML String like this
<resp><status>good</status><msg>hi</msg></resp>
I follow this help
Simplest way to query XML in Java
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
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
-
Waqas Ali about 11 yearsso if i have many nodes then i have to create source for each of them? is there any better solution?
-
Ravi K Thapliyal about 11 yearsUse a
DocumentBuilderFactory
to build aDocument
(part of JAXP DOM APIs) that can be reused across multiple Xpath evaluations. -
Paul Alexander over 10 yearsout of interest, if the XML string was <status>good, ok</status> is there anyway of just selecting the first word in the string before the comma? or just selecting the word after the comma?
-
McDowell over 10 years@brookman Not with Java's XPath support. You might be able to with XPath 2 - see the Saxon API.
-
Alexey Grigorev over 9 yearsThis library is very nice, but what I don't like is that it brings aspectj with it - which I don't think is really necessary
-
yegor256 over 9 yearsYeah, we're planning to get rid of that very soon
-
Alexey Grigorev over 9 yearsthat would be very nice! any RSS I can subscribe for to keep myself up-to-date?
-
yegor256 over 9 years@AlexeyGrigorev follow/watch this ticket: github.com/jcabi/jcabi-xml/issues/61