【问题标题】:How to locate duplicate XML elements via Xpaths using Java如何使用 Java 通过 Xpaths 定位重复的 XML 元素
【发布时间】:2016-03-14 21:25:57
【问题描述】:

我调用 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>

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

/Error/FormCd

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

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

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

任何想法我可以如何操作给定的 XML,以便我可以轻松地获得我想要的元素?也许为所有具有超过 1 个根元素的响应编写一个新的 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)

【问题讨论】:

  • 您的选择标准未指定,并且您的 XML 格式不正确。说明您希望在 Error 元素中进行选择的具体标准,并向您的 XML 添加一个公共根元素。
  • 是的,这是我的问题的一部分。我正在调用 API,API 使用格式错误的 XML 响应我,如原始帖子中所示。我想通过 XPATH 以编程方式 (java) 解析 XML 并检索某些值,例如 ` /Error/FormCd` 。也许我应该用一个新的根节点(例如AllErrors)来附上响应,这样就只有1个根节点。因此,添加到我的标准中,我会说将这种格式错误的 XML 转换为格式良好的 XML。

标签: java regex xml xpath xml-parsing


【解决方案1】:

您可以将您的响应包含在一个名为 的新 xml 节点中。你的xpath也是错误的。

/Error/FormCd[0]

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

/Error/FormCd[2]

为您提供所有 中的第二个 元素。据我所知,您的所有 中只有一个 。你应该做的是:

/Error[1]/FormCd

这为您提供了第一个

中的所有 (在本例中为一个)

【讨论】:

  • 我这里的问题是因为我试图包装的 XML 格式不正确(由于有多个根节点),这是我试图解决的问题!我遇到的循环问题
  • 我不是 java 开发者,所以没有。但是在文件/字符串的开头添加 并在末尾添加 应该不难。之后你就有了一个格式良好的 xml 文件。
【解决方案2】:

将所有错误元素添加到列表,然后为其创建容器,可以使格式错误的 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 库来执行 XPaths。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-31
    • 2016-01-28
    • 2015-02-23
    • 1970-01-01
    相关资源
    最近更新 更多