web-dev-qa-db-ja.com

Java XPathを使用してXML単純文字列を解析する

私はこのようなXML文字列を持っています

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

このヘルプに従います

JavaでXMLをクエリする最も簡単な方法

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


}

メッセージノード値を取得したいが、例外が発生した

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

この単純なタスクに外部ライブラリを使用するつもりはありません。他のノードの値を取得する方法を教えてください。ありがとう

31
Waqas Ali

同じInputSourceを複数のevaluate()呼び出しに再利用することはできません。自動的に閉じられるためです。したがって、Stream closed IO exception。これを試してください

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

編集:
より良いアプローチは、DocumentBuilderFactoryを使用してXMLを解析し、最初に(JAXPのDOM APIを使用して)Documentを構築し、それを複数の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

ラビの解 は次のようにも表現できます:

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

あなたが試すことができます - jcabi-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);
6
yegor256