Java 如何将xml解析为hashmap?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27547292/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 04:34:50  来源:igfitidea点击:

how to parse xml to hashmap?

javaxml

提问by yanivshe

I have an example of an xml I want to parse

我有一个要解析的 xml 示例

 <?xml version="1.0" encoding="utf-8"?>

<Details>
    <detail-a>

        <detail> attribute 1 of detail a </detail>
        <detail> attribute 2 of detail a </detail>
        <detail> attribute 3 of detail a </detail>

    </detail-a>

    <detail-b>
        <detail> attribute 1 of detail b </detail>
        <detail> attribute 2 of detail b </detail>

    </detail-b>


</Details>

I would like from this xml to write a method that will parse it to hashmap that the key is a string and the value is a list of strings.

我想从这个 xml 中编写一个方法,将它解析为 hashmap 键是一个字符串,值是一个字符串列表。

for instance : key "detail a" value={"attribute 1 of detail a","attribute 2 of detail a","attribute 3 of detail a"}

例如:key "detail a" value={"attribute 1 of detail a","attribute 2 of detail a","attribute 3 of detail a"}

and so on..

等等..

what is the best way to do this ? because I got confused :\

做这个的最好方式是什么 ?因为我很困惑:\

I got this far to try to print detail-a and detail-b but I get blank...

我走了这么远试图打印 detail-a 和 detail-b 但我得到了空白......

public static void main(String[] args) {
    // TODO Auto-generated method stub

    DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();

        DocumentBuilder builder;
        try {
            builder = factory.newDocumentBuilder();
            File f= new File("src/Details.xml");
            Document doc=builder.parse(f);
            Element root=doc.getDocumentElement();
            NodeList children=root.getChildNodes();
            for(int i=0;i<children.getLength();i++)
            {
                Node child=children.item(i);
                if (child instanceof Element)
                {
                    Element childElement=(Element) child;
                    Text textNode=(Text)childElement.getFirstChild();
                    String text=textNode.getData().trim();
                    System.out.println(text);

                }
            }

        } catch (ParserConfigurationException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();   
        } catch (SAXException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

采纳答案by MihaiC

Use JAXBto read from xmland save it to a custom object.

使用JAXB从读取xml并保存为自定义对象。

Custom object class:

自定义对象类:

import java.util.List;

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

@XmlRootElement(name = "Details")
@XmlType(propOrder = { "detailA", "detailB" })
public class Details {
    private List<String> detailA;
    private List<String> detailB;

    public void setDetailA(List<String> detailA) {
        this.detailA = detailA;
    }

    @XmlElementWrapper(name = "detail-a")
    @XmlElement(name = "detail")
    public List<String> getDetailA() {
        return detailA;
    }

    public void setDetailB(List<String> detailB) {
        this.detailB = detailB;
    }

    @XmlElementWrapper(name = "detail-b")
    @XmlElement(name = "detail")
    public List<String> getDetailB() {
        return detailB;
    }
}

Extract the data from your xml into the object, then add contents to a map as desired:

将 xml 中的数据提取到对象中,然后根据需要将内容添加到地图中:

public static void main(String[] args) throws JAXBException, FileNotFoundException {
    System.out.println("Output from our XML File: ");
    JAXBContext context = JAXBContext.newInstance(Details.class);
    Unmarshaller um = context.createUnmarshaller();
    Details details = (Details)um.unmarshal(new FileReader("details.xml"));
    List<String> detailA = details.getDetailA();
    List<String> detailB = details.getDetailB();

    Map<String, String[]> map = new HashMap<String, String[]>();
    map.put("detail-a", detailA.toArray(new String[detailA.size()]));
    map.put("detail-b", detailB.toArray(new String[detailB.size()]));


    for (Map.Entry<String, String[]> entry : map.entrySet()) {
        //key "detail a" value={"attribute 1 of detail a","attribute 2 of detail a","attribute 3 of detail a"}
        System.out.print("Key \"" +entry.getKey()+"\" value={");
        for(int i=0;i<entry.getValue().length;i++){
            if(i!=entry.getValue().length-1){
                System.out.print("\""+entry.getValue()[i]+"\",");
            }
            else{
                System.out.print("\""+entry.getValue()[i]+"\"}");
            }
        }
        System.out.println();
    }
}

Output will be:

输出将是:

Output from our XML File: 
Key "detail-a" value={"attribute 1 of detail a","attribute 2 of detail a","attribute 3 of detail a"}
Key "detail-b" value={"attribute 1 of detail b","attribute 2 of detail b"}

As a note: this will work only for the xml you provided as input in your question, if you need to add more details like detail-cand so on you must define them in your custom object as well.

请注意:这仅适用于您在问题中作为输入提供的 xml,如果您需要添加更多详细信息detail-c,诸如此类,您还必须在自定义对象中定义它们。

XML used:

使用的 XML:

<?xml version="1.0" encoding="utf-8"?>
<Details>
    <detail-a>
        <detail>attribute 1 of detail a</detail>
        <detail>attribute 2 of detail a</detail>
        <detail>attribute 3 of detail a</detail>
    </detail-a>
    <detail-b>
        <detail>attribute 1 of detail b</detail>
        <detail>attribute 2 of detail b</detail>
    </detail-b>
</Details>

回答by Cfx

I can not resist to present a much shorter solution using XMLBeamthat works with any number of "detail-x" subelements.

我无法抗拒使用XMLBeam提出一个更短的解决方案,该解决方案适用于任意数量的“detail-x”子元素。

public class Tetst {

@XBDocURL("resource://test.xml")
public interface Projection {
    @XBRead("name()")
    String getName();

    @XBRead("./detail")
    List<String> getDetailStrings();

    @XBRead("/Details/*")
    List<Projection> getDetails();
}

@Test
public void xml2Hashmap() throws IOException {
    HashMap<String, List<String>> hashmap = new HashMap<String, List<String>>();
    for (Projection p : new XBProjector().io().fromURLAnnotation(Projection.class).getDetails()) {
        System.out.println(p.getName() + ": " + p.getDetailStrings());
        hashmap.put(p.getName(), p.getDetailStrings());
    }
}
}

This prints out

这打印出来

detail-a: [ attribute 1 of detail a ,  attribute 2 of detail a ,  attribute 3 of detail a ]
detail-b: [ attribute 1 of detail b ,  attribute 2 of detail b ]

for your example test.xml and fills a Hashmap.

对于您的示例 test.xml 并填充一个 Hashmap。

回答by Valentyn Kolesnikov

There is underscore-javalibrary. Or it's java 8 port. I am the maintainer of the project. Live example

下划线-java库。或者它是java 8 port。我是项目的维护者。活生生的例子

import com.github.underscore.lodash.U;
import java.util.Map;

public class Main {

  @SuppressWarnings("unchecked")
  public static void main(String[] args) {

    Map<String, Object> map = (Map<String, Object>) U.fromXml(
        "<Details>\r\n" + 
        "    <detail-a>\r\n" + 
        "\r\n" + 
        "        <detail> attribute 1 of detail a </detail>\r\n" + 
        "        <detail> attribute 2 of detail a </detail>\r\n" + 
        "        <detail> attribute 3 of detail a </detail>\r\n" + 
        "\r\n" + 
        "    </detail-a>\r\n" + 
        "\r\n" + 
        "    <detail-b>\r\n" + 
        "        <detail> attribute 1 of detail b </detail>\r\n" + 
        "        <detail> attribute 2 of detail b </detail>\r\n" + 
        "\r\n" + 
        "    </detail-b>\r\n" + 
        "\r\n" + 
        "\r\n" + 
        "</Details>");

    System.out.println(map);
    // {Details={detail-a={detail=[ attribute 1 of detail a ,  attribute 2 of detail a ,  attribute 3 of detail a ]},
    // detail-b={detail=[ attribute 1 of detail b ,  attribute 2 of detail b ]}}, #omit-xml-declaration=yes}
  }
}