web-dev-qa-db-fra.com

Analyser une chaîne simple XML à l'aide de Java XPath

J'ai une chaîne XML comme celle-ci

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

Je suis cette aide

moyen le plus simple d'interroger XML en 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);


}

Je veux obtenir la valeur du nœud msg mais j'ai une 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

Je ne vais pas utiliser de bibliothèque externe pour cette tâche simple. veuillez me guider comment obtenir les valeurs des autres nœuds. Merci

31
Waqas Ali

Vous ne pouvez pas réutiliser la même InputSource pour plusieurs appels evaluate() car elle est automatiquement fermée. Vous obtenez donc le Stream closed IO exception. Essayez ceci

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);

MODIFIER:
Une meilleure approche serait d'utiliser une DocumentBuilderFactory pour analyser votre XML et créer d'abord une Document (en utilisant les API DOM de JAXP) qui peut ensuite être réutilisée dans plusieurs évaluations 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);
47
Ravi Thapliyal

solution de Ravi peut également s'exprimer comme suit:

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);
12
McDowell

Tu peux essayer jcabi-xml , qui effectue des manipulations DOM en arrière-plan:

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);
6
yegor256