如何解析XML以从中返回Map?

时间:2015-04-15 11:04:59

标签: java xml xml-parsing

我想解析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,并且关键字应该是关于所有其他孩子应该存储在列表中的关键字 确切地说,它应该是这样的<key=echo ,List=ln ,cd,data0,data1,data2,data3>

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

3 个答案:

答案 0 :(得分:2)

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轻松解析。为文档的根创建一个类,我将其称为Root。为数据元素创建一个类,我将其称为Data

Class Root:

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

班级数据:

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

然后是一个带有main函数的类,它将从当前目录中名为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数据的格式,则此解决方案将无效。

答案 1 :(得分:1)

虽然我认为这个问题有点奇怪,但我同意以一种可以使用SAX或DOM的方式重新思考问题可能是明智的,你可以使用一个简单的XmlPullParser来实现这一点。 / p>

假设您的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;
        }
    }

答案 2 :(得分:0)

  

我想最大限度地减少编码工作,因此SAX和DOM解析器永远不会出现在我的雷达上。

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

XML绑定依赖于某种XML模式来赋予它们牵引力。它看起来不像XML的架构。

对于它的价值,您可以在50到100行Java代码中为这个用例编写基于DOM的提取器。这不是一项巨大的编码工作,而且可能不如在互联网上寻找替代方案。