如何使用Java

时间:2016-03-14 21:25:58

标签: java regex xml xpath xml-parsing

我打电话给API,我收到以下回复:

<Error>
    <FormCd>940</FormCd>
    <MetaData>
        <Entry>
            <Key>Balance Due</Key>
            <Value>1500.99</Value>
        </Entry>
    </MetaData>
 </Error>

 <Error>
    <FormCd>941</FormCd>
    <MetaData>
        <Entry>
            <Key>Node</Key>
            <Value>/Return/ReturnHeader/Filer/USAddress/ZIPCd</Value>
        </Entry>
    </MetaData>
 </Error>

 <Error>
    <FormCd>942</FormCd>
    <MetaData>
        <Entry>
            <Key>Description</Key>
            <Value>Wages Amount</Value>
        </Entry>
        <Entry>
            <Key>LineNumber</Key>
            <Value>2</Value>
        </Entry>
    </MetaData>
 </Error>

如何通过使用Xpath的常见元素在该文档中唯一标识/定位元素。我的意思是,当我尝试执行以下Xpath时:

/Error/FormCd

我收到错误,因为此Xpath有3个可能的值。由于这里有3个根元素,我不能这样做:

/Error/FormCd[0]
/Error/FormCd[1]
/Error/FormCd[2]

索引的Xpath不会起作用,因为我有超过1个根元素。

任何想法如何操纵给定的XML以便我可以轻松找到我想要的元素?也许为所有具有多个根元素的响应编写新的XML文档?把它全部置于1个根元素之下即错误?这可能太昂贵了。任何帮助或想法将不胜感激。谢谢。

修改

尝试使用以下实现添加根标记,将格式错误的XML转换为格式良好的XML:

    try {
        // String f = FileUtils.readFileToString(new File(file));

        InputStream is = new FileInputStream(file);
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();

        Document oldDoc = builder.parse(is);
        Node oldRoot = oldDoc.getDocumentElement();

        Document newDoc = builder.newDocument();
        Element newRoot = newDoc.createElement("AllErrors");
        newDoc.appendChild(newRoot);
        newRoot.appendChild(newDoc.importNode(oldRoot, true));

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        DOMSource domSource = new DOMSource(newDoc);

        File fil = new File("newXml.xml");
        StreamResult result = new StreamResult(fil);

        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        transformer.transform(domSource, result);

        System.out.println(out);


    }

    catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ParserConfigurationException e) {
        e.printStackTrace();
    } catch (SAXException e) {
        e.printStackTrace();
    } catch (TransformerException e) {
        e.printStackTrace();
    }

我得到的错误是:

[Fatal Error] :21:3: The markup in the document following the root element must be well-formed.
org.xml.sax.SAXParseException; lineNumber: 21; columnNumber: 3; The markup in the document following the root element must be well-formed.
    at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
    at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
    at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:121)
    at com.intuit.ctg.taxengine.automation.calc.ErrorXML.test(ErrorXML.java:48)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)

2 个答案:

答案 0 :(得分:1)

您可以将响应包含在名为&lt; root&gt;的新xml节点中。你的xpath也错了。

/Error/FormCd[0]

不可能,因为xpath索引从1开始。此外:

/Error/FormCd[2]

给你第二个&lt; FormCd&gt;来自所有&lt;错误&gt;的元素。据我所知,你只有一个&lt; FormCd&gt;在你的所有&lt;错误&gt;。你应该做的是:

/Error[1]/FormCd

从第一个&lt; Error&gt;

中为您提供所有&lt; FormCd&gt;(在本例中为一个)

答案 1 :(得分:0)

将所有Error元素添加到List中,然后为其创建容器,可以生成格式错误的XML,格式正确。

List<InputStream> streams = 
        Arrays.asList(new ByteArrayInputStream("<AllErrors>".getBytes()), inputStream, 
                new ByteArrayInputStream("</AllErrors>".getBytes()) );

container = new SequenceInputStream(Collections.enumeration(streams));
wellFormedXML = IOUtils.toString(container);

从这里我可以使用java的XPATH库来执行XPath。