how to parse xml to hashmap?

后端 未结 3 854
北荒
北荒 2021-01-12 20:17

I have an example of an xml I want to parse

 

a
相关标签:
3条回答
  • 2021-01-12 20:33

    Use JAXB to read from xml and save it to a custom object.

    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:

    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-c and so on you must define them in your custom object as well.

    XML used:

    <?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>
    
    0 讨论(0)
  • 2021-01-12 20:33

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

    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.

    0 讨论(0)
  • 2021-01-12 20:44

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

    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 = U.fromXmlMap(
            "<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}
      }
    }
    
    0 讨论(0)
提交回复
热议问题