0

I am trying to convert any given xml to hash map. I know this can somehow be done using JAXB. I was trying using jsoup. My code is below

 public static Map<String,Object> xmlToMapAll(String xml){
            List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
            Map<String,Object> map = new HashMap<String,Object>();
            try{
                Document xmlDoc = Jsoup.parse(xml, "", Parser.xmlParser());
                Elements eles =xmlDoc.getAllElements();
                for(Element ele: eles){
                    Map<String,Object> mi = new HashMap<String,Object>();
                    if(ele.children().size()>1){
                        mi = getChilds(ele.children());
                    }else{
                        mi.put(ele.tagName(), ele.ownText());
                    }
                    list.add(mi);
                    //map.putAll(mi);
                }

                map.put("data", list);
                map.put("Status", "SUCCESS");
            }catch(Exception ce){
                log.error("IndoXMLParseUtil.xmlToMapAll() ce "+IndoUtil.getFullLog(ce));
            }
            return map;
        }
        public static Map<String,Object> getChilds(Elements childs){
            Map<String,Object> map = new HashMap<String,Object>();
            for(Element child: childs){
                if(child.children().size()>0){
                    map = getChilds(child.children());
                }else{
                    map.put(child.tagName(), child.ownText());
                }
            }
            return map;
        }

    public static void main(String args[]){
            String xml="<ExtMessage xmlns=\"com/test/schema/evExtQMainPkgQuotaResp\">   
<ExtQMainPkgQuotaResp>     
<ServiceNumber>1234567</ServiceNumber>
<Source><a>10</a><b>11</b><a>12</a></Source>
<Status>Success</Status>
    <ErrorMessage/><InitialQuota>2621440</InitialQuota> 
        <UsedQuota>62859.49</UsedQuota>   
    </ExtQMainPkgQuotaResp> </ExtMessage> ";
                Map<String, Object>  ds =  xmlToMapAll(xml);
                System.out.println("IndoXMLParseUtil.main() "+ds);
            }

output:

{Status=SUCCESS, data=[{#root=}, {extmessage=}, {errormessage=, b=11, status=Success, a=12, initialquota=2621440, usedquota=62859.49}, {servicenumber=6285770355730}, {b=11, a=12}, {a=10}, {b=11}, {a=12}, {status=Success}, {errormessage=}, {initialquota=2621440}, {usedquota=62859.49}]}

Problem is I am getting repeated data. Also I believe there are always better ideas out here.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Aadam
  • 1,521
  • 9
  • 30
  • 60
  • Not sure if checked already but this should help http://stackoverflow.com/questions/1537207/how-to-convert-xml-to-java-util-map-and-vice-versa & using jaxb http://stackoverflow.com/questions/27547292/how-to-parse-xml-to-hashmap – Sheetal Mohan Sharma Mar 09 '16 at 15:22
  • looking into XStream. If that goes easy will let you know. – Aadam Mar 09 '16 at 15:28
  • K I have used an X Stream sample with the XML given in question. That is not able to parse my XML completely. like we need to provide root element and aliases and so on. The problem is my XML keep changing at run time. I just need something which could represent XML directly in java object. I don't want to change or modify it. – Aadam Mar 09 '16 at 15:46
  • What is the expected output? – Davide Pastore Mar 10 '16 at 09:08
  • I am expecting xml in map and list of maps – Aadam Mar 10 '16 at 09:10

1 Answers1

0

This is an simple example using W3C DOM parser, so there's a lot that can be improved.

Also, you'll have to define a criteria to resolve possible key collission. With this code, only the last <a> from <Source> will be saved to the map.

public static Map<String, Object> xmlToMapAll(String xml) throws ParserConfigurationException
{
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    DocumentBuilder db = dbf.newDocumentBuilder();

    List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
    Map<String, Object> map = new HashMap<String, Object>();
    try
    {
        InputStream stream = new ByteArrayInputStream(xml.getBytes("UTF-8"));

        Document xmlDoc = db.parse(stream);

        Element rootNode = xmlDoc.getDocumentElement();

        NodeList eles = rootNode.getChildNodes();

        for (int i = 0; i < eles.getLength(); i++)
        {
            Node ele = (Node) eles.item(i);

            Map<String, Object> mi = new HashMap<String, Object>();

            if (ele.getChildNodes().getLength() > 1 && ele.getNodeType() == Node.ELEMENT_NODE)
            {
                mi.put(ele.getNodeName(), getChilds(ele.getChildNodes()));
            }
            else
            {
                Node subChild = ele.getFirstChild();

                if (subChild != null)
                {
                    if (!subChild.hasChildNodes())
                    {
                        mi.put(ele.getNodeName(), subChild.getNodeValue());
                    }
                    else
                    {
                        mi.put(ele.getNodeName(), "");
                    }
                }
            }

            if (!mi.isEmpty())
            {
                list.add(mi);
            }
        }

        map.put("data", list);
        map.put("Status", "SUCCESS");
    }
    catch (Exception ce)
    {
         log.error("IndoXMLParseUtil.xmlToMapAll() ce " + IndoUtil.getFullLog(ce));
    }
    return map;
}

public static Map<String, Object> getChilds(NodeList childs)
{
    Map<String, Object> map = new HashMap<String, Object>();
    for (int a = 0; a < childs.getLength(); a++)
    {
        Node child = (Node) childs.item(a);

        if (child.getNodeType() == Node.ELEMENT_NODE)
        {
            if (child.getChildNodes().getLength() > 1)
            {
                map.put(child.getNodeName(), getChilds(child.getChildNodes()));
            }
            else
            {
                Node subChild = child.getFirstChild();

                if (subChild != null && !subChild.hasChildNodes())
                {
                    map.put(child.getNodeName(), subChild.getNodeValue());
                }
                else
                {
                    map.put(child.getNodeName(), "");
                }
            }
        }
    }
    return map;
}

public static String getNodeValue(Node node)
{
    String result = "";

    final NodeList childs = node.getChildNodes();

    for (int i = 0; i < childs.getLength(); i++)
    {
        final Node child = childs.item(i);
        if (child != null)
        {
            if ((child.getNodeType() == Node.TEXT_NODE) || (child.getNodeType() == Node.CDATA_SECTION_NODE))
            {
                result += child.getNodeValue().trim();
            }
        }
    }
    return result;
}
delephin
  • 1,085
  • 1
  • 8
  • 10