如何从中解析 XML 到 return 一个 Map?

How to parse XML to return a Map from it?

我想解析如下所示的 XML:

<ROOT>
   <ECHO>
        <column1>NAME</column1>
        <column2>LN</column2>
        <column3>CD</column3>
        <column4>DATA0</column4>
        <column5>DATA1</column5>
        <column6>DATA2</column6>
        <column7>DATA3</column7>
   </ECHO>
   <ECHO1>
        <column1>NAME</column1>
        <column2>LN</column2>
        <column3>CD</column3>
        <column4>DATA0</column4>
   </ECHO1>
</ROOT>

这里我想要一个 Map 被返回并且不知何故密钥应该是并且相对于所有其他 children 应该存储在列表中 准确来说应该是这样的 <key=echo ,List=ln ,cd,data0,data1,data2,data3>.

我尝试探索 JAXB,但我认为这对我的情况没有帮助,因为 children 的名称在每种情况下都不相同,所以我无法在任何模型中定义静态字段数并解组 XML 建模。我想尽量减少编码工作,因此 SAX 和 DOM 解析器永远不会出现在我的雷达上。任何人都可以在没有太多编码的情况下提供任何线索吗?

I want to minimize the coding effort so SAX and DOM parser is never on my radar.

我认为您需要重新校准雷达 :-) 我怀疑 SAX 或 DOM 或类似的方法是最简单的方法。

XML 绑定依赖于某种 ​​XML 模式来提供牵引力。您的 XML.

似乎无法使用架构

对于它的价值,您可以在 50 到 100 行 Java 代码中为此用例编写一个基于 DOM 的提取器。这不是一项巨大的编码工作,而且可能比在互联网上搜索替代品要省力。

虽然我确实认为这个问题有点奇怪,并且我同意以可以使用 SAX 或 DOM 的方式重新考虑问题可能是明智的,但您可以使用一个简单的XmlPullParser 来完成这个。

假设您的 XML 始终根据您的示例构建 w.r.t 键、值等的深度,并假设您想要的输出是 Map<String, List<String>>,您可能能够做类似的事情:

    int eventType;
    String key = null;
    List<String> value = null;
    HashMap<String, List<String>> map = new HashMap<String, List<String>>();

    while ((eventType = xpp.getEventType()) != XmlPullParser.END_DOCUMENT) {
        switch (eventType) {
            case XmlPullParser.START_TAG:
                if (xpp.getDepth() == 2) {
                    key = xpp.getName();
                    value = new ArrayList<String>();
                }
                break;

            case XmlPullParser.TEXT:
                if (xpp.getDepth() == 3) {
                    value.add(xpp.getText());
                }
                break;

            case XmlPullParser.END_TAG:
                if (xpp.getDepth() == 2) {
                    map.put(key, value);
                }
                break;
        }
    }

Beggs 基本上是问你对XML格式有没有控制权,也就是能不能稍微修改一下?你还没有回答这个问题。

假设可以。以下是您的原始 XML 的略微修改版本:

<ROOT>
    <data name="ECHO">
        <column>NAME</column>
        <column>LN</column>
        <column>CD</column>
        <column>DATA0</column>
        <column>DATA1</column>
        <column>DATA2</column>
        <column>DATA3</column>
    </data>
    <data name="ECHO1">
        <column>NAME</column>
        <column>LN</column>
        <column>CD</column>
        <column>DATA0</column>
    </data>
</ROOT>

这可以很容易地用 JAXB 解析。为文档的根创建一个class,我将其命名为Root。为数据元素创建一个class,我将其命名为Data

Class根目录:

import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="ROOT")
public class Root {
    @XmlElement
    public List<Data> data;
}

Class数据:

import java.util.List;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;

public class Data {
    @XmlAttribute
    public String name;
    @XmlElement
    public List<String> column;
}

然后是一个 class,其主要功能将从当前目录中名为 test.xml 的文件加载 XML 文件。然后数据将传输到 Map 并打印地图以显示其内容。

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;

public class Test {

    public static void main(String[] args) throws Exception {
        JAXBContext ctx = JAXBContext.newInstance(Root.class);
        Unmarshaller um = ctx.createUnmarshaller();
        Root root = (Root) um.unmarshal(new File("test.xml"));
        // XML is now loaded. Turn it into a Map
        Map<String,List<String>> map = new HashMap<String, List<String>>();
        for (Data data : root.data) {
            map.put(data.name, data.column);
        }
        System.out.println(map);    // Easily show content
    }
}

如果您无法控制 XML 数据的格式,此解决方案将不起作用。