views:

863

answers:

4

I need to parse xml into a HashMap where the 'key' is the concatenation of two elements attributes. The xml looks like :

<map>
  <parent key='p1'><child key='c1'> value1</child></parent>
  <parent key='p2'><child key='c2'> value1</child></parent>
</map>

In the 1st entry of map, I want to put 'p1.c1'as the map key while 'value1' as the map value. How to achieve that?

A: 

Do you have problem selecting and using XML parsers?

mokito
no 100% , I want to use apache commons digester to do that. it works for single hierarchy. but for multi-hierarchy object. The question is , howto get parent key name , child keyname and put them together?
ariso
+1  A: 

Apache common digest is not really a fully parser and it is sometimes very very slow... if you have to deal with large XML documents you probably want to check out extended VTD-XML, which supports up to 256 GB of XML, it also supports memory map, allowing partial loading of XmL document

vtd-xml-author
+1  A: 

An example using Xstream (http://xstream.codehaus.org). It does not completely follow your XML spec, I added nested <value> tags to the <child> tags.

Output:

<map>
  <parent key="p1">
    <child key="c1">
      <value>value1</value>
    </child>
  </parent>
  <parent key="p2">
    <child key="c2">
      <value>value1</value>
    </child>
  </parent>
</map>
p1.c1=value1
p2.c2=value1

Does this help? Otherwise please follow up.

import java.util.HashMap;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

public class MapParser {

    public static void main(String[] args) {

     XStream xstream = new XStream(new DomDriver());
     xstream.alias("map", Map.class);
     xstream.addImplicitCollection(Map.class, "parents");
     xstream.alias("parent", Parent.class);
     xstream.useAttributeFor(Parent.class, "key");
     xstream.alias("child", Child.class);
     xstream.useAttributeFor(Child.class, "key");

     Map map = (Map) xstream
       .fromXML("<map><parent key='p1'><child key='c1'><value>value1</value></child></parent><parent key='p2'><child key='c2'><value>value1</value></child></parent></map>");

     System.out.println(xstream.toXML(map));

     java.util.Map result = new HashMap();
     for (Parent parent : map.getParents()) {

      Child child = parent.getChild();
      String key = parent.getKey() + "." + child.getKey();
      result.put(key, child.getValue());
      System.out.println(key + "=" + child.getValue());
     }
    }
}


import java.util.ArrayList;
import java.util.List;

public class Map {

    private List<Parent> parents = new ArrayList<Parent>();

    public void addParent(Parent parent) {
     parents.add(parent);
    }

    public List<Parent> getParents() {
     return this.parents;
    }
}

public class Parent {

    private String key;
    private Child child;

    public Parent(String key) {
     this.key = key;
    }

    public Child getChild() {
     return child;
    }

    public void setChild(Child child) {
     this.child = child;
    }

    public String getKey() {
     return key;
    }

    public void setKey(String key) {
     this.key = key;
    }
}


public class Child {

    private String key;
    private String value;

    public Child(String key) {
     this.key = key;
    }

    public String getKey() {
     return key;
    }

    public void setKey(String key) {
     this.key = key;
    }

    public String getValue() {
     return value;
    }

    public void setValue(String value) {
     this.value = value;
    }
}
Adriaan Koster
let me try, thanks
ariso
but... does they any solution used digester? it works for 99% cases.and this is the one we can not handle within digester.
ariso
Show us some code! It will make it much easier to help you.
Adriaan Koster
A: 

Resolved. user extend hashmap rule.

ariso