2013-05-23 11 views
29

Ho stringa XML come questoParse XML semplice stringa usando Java XPath

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

seguo questo aiuto

Simplest way to query XML in Java

mycode:

voglio arrivare msg valore del nodo ma ho ottenuto l'eccezione

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 

Non ho intenzione di utilizzare alcuna libreria esterna per questo semplice compito. per favore guidami come ottenere i valori di altri nodi. Grazie

+0

Messaggio tutto il vostro metodo se si desidera aiuto .. –

+0

Non aspettarti molto aiuto condividendo solo una riga di codice. –

risposta

38

Non è possibile riutilizzare lo stesso InputSource per più chiamate evaluate() perché è automaticamente chiuso. Quindi stai ricevendo l'eccezione IO. Prova questo

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:
Un approccio migliore sarebbe quella di utilizzare un DocumentBuilderFactory per analizzare il tuo XML e costruire un Document prima (utilizzando le API DOM di JAXP), che possono poi essere riutilizzata tra diverse valutazioni 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

quindi se ho molti nodi devo creare il codice sorgente per ognuno di essi? c'è una soluzione migliore? –

+0

Utilizzare un 'DocumentBuilderFactory' per creare un' Document' (parte delle API DOM JAXP) che può essere riutilizzato su più valutazioni Xpath. –

+0

Controllare l'aggiornamento. Aggiunto del codice per aiutarti a iniziare. –

11

Ravi's solution può anche essere espresso come:

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

di interesse, se la stringa XML era buona, ok c'è comunque solo la selezione della prima parola nella stringa prima della virgola? o semplicemente selezionando la parola dopo la virgola? –

+0

@brookman Non con il supporto XPath di Java. Potresti essere in grado di usare XPath 2 - vedi l'API Saxon. – McDowell

6

Si può provare jcabi-xml, che fa manipolazioni DOM dietro la scena:

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

Questa libreria è molto bella, ma ciò che non mi piace è che porta l'aspetto con esso - che non penso sia davvero necessario –

+0

Sì, abbiamo intenzione di sbarazzarci di quello molto presto – yegor256

+0

che sarebbe molto simpatico! qualsiasi RSS che posso sottoscrivere per tenermi aggiornato? –