Search code examples
javaxmlconfiguration-files

What is the most elegant way to read map from xml file using Apache Commons Configuration 2.5?


I have almost the same problem as in this question. Let's say I have a similar xml file and I want to read the first map:

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <map>
    <entry key="favoriteSeason">summer</entry>
    <entry key="favoriteFruit">pomegranate</entry>
    <entry key="favoriteDay">today</entry>
  </map>
  <anotherMap>
    <entry key="favoriteSeason">winter</entry>
    <entry key="favoriteFruit">orange</entry>
    <entry key="favoriteDay">wednesday</entry>
    <entry key="favoriteColor">green</entry>
  </anotherMap>
</root>

Note: number of key-value pairs may vary.

The answer in linked question which uses ConfigurationNode is good but in 2.5 version this class doesn't exist. Following Apache's user's guide I came up with something like this:

Configurations configurations = new Configurations();
XMLConfiguration xmlConfiguration = configurations.xml("config.xml");
Map<String, String> map = new HashMap<>();
int pairsCount = xmlConfiguration.getList(String.class, "map.entry").size();
for(int i = 0; i < pairsCount; ++i)
  map.put(xmlConfiguration.getString("map.entry(" + i + ")[@key]"), xmlConfiguration.getString("map.entry(" + i + ")"));

I feel that getting number of key-value pairs isn't the best and putting pairs in map is also not that readable. Is there a better way to do this?


Solution

  • Hope this helps.

    public static void main(String[] args) throws ConfigurationException {
        Configurations configurations = new Configurations();
        XMLConfiguration xmlConfiguration = configurations.xml("config.xml");
        Map<String, Map<String, String>> map = new HashMap<>();
        xmlConfiguration.getNodeModel().getRootNode().getChildren().forEach(x -> {
            Map<String, String> temp = new HashMap<>();
            x.getChildren().forEach(y -> {
                temp.put(y.getAttributes().get("key").toString(), y.getValue().toString());
            });
            map.put(x.getNodeName(), temp);
        });
        System.err.println(map);
    }
    

    Output Map for your example :

     {
        anotherMap={
            favoriteDay=wednesday, 
            favoriteColor=green,
            favoriteSeason=winter, 
            favoriteFruit=orange
           },
       map={
           favoriteDay=today, 
           favoriteSeason=summer, 
           favoriteFruit=pomegranate}
        }
    

    Here i am creating map which will contain two map in it corrsponding to key map and anothermap as per your exmple xml.