Search code examples
javasmartgwtapache-commons-digester

Digester: Extracting node name for a map<tagname, value>


My question is close to this one: Digester: Extracting node name

Even with the answer, I can't find out.

Here is my xml file (from smartgwt RestDataSource POST):

<data>
  <isc_OID_14>
    <attribute1>value1</attribute1>
    <attribute2>value2</attribute2>
  </isc_OID_14>
</data>

I would like to create, with Commons Digester, the following map : {attribute1=value1, attribute2=value2}

I already have those lines:

digester = new Digester();
digester.addObjectCreate("data", HashMap.class);
// some "put" rules matching something like data/*
return digester.parse(myFile);

I do not know the list nor the name of tags in the <data><sourceId /></data>. isc_OID_14 or attribute1 can be named foobar or id or attribute335...


Solution

  • I think something like this is what you want:

    import java.io.*;
    import java.util.*;
    import org.apache.commons.digester.*;
    
    public class DigestToMap {
        @SuppressWarnings("unchecked")
        public static void main(String[] args) throws Exception {
            File file = new File("digestme.xml");
            Digester digester = new Digester();
            digester.setRules(new ExtendedBaseRules());
            digester.addObjectCreate("data", HashMap.class);
            digester.addRule("data/?", new Rule() {
                @Override public void end(String nspace, String name) {
                    ((HashMap<String,String>)getDigester().peek()).put("[ID]", name);
                }
            });
            digester.addRule("*", new Rule() {
                @Override public void body(String nspace, String name, String text) {
                    ((HashMap<String,String>)getDigester().peek()).put(name, text);
                }
            });
            Map<String,String> map = (Map<String,String>) digester.parse(file);
            System.out.println(map);
        }
    }
    

    Basically it uses ExtendedBaseRules for the wildcard matching.

    There are 3 rules:

    • On data, ObjectCreate a HashMap
    • On data/? (direct child of data), map [ID]=name (make this Rule a no-op if not needed)
    • On * (everything else), map name=text

    On my machine, this prints:

    {[ID]=isc_OID_14, attribute1=value1, attribute2=value2}
    

    API links