Tag Archive for 'mapping'

Parsing XML Using Castor

Castor provides 3 ways to parse an xml file into java objects. I have used two of those, and am writing this post to give an introduction into the method.

The first way is to create java classes for each of the elements and then use the marshall and unmarshall methods to parse the xml file. Castor uses introspection techniques to map elements with fields of the java class. I have not used this method, and will not go any further.

The second and perhaps the easiest way is to give Castor the schema file and let it generate the java classes. Say you have the following schema file:

If you let Castor generate the java source files itself, the following files are generated: The Plgen class for the root element:

The Playlist class which is the child of Plgen:

And finally, the ExtensionType enum:

But I ran into trouble when I wanted to add additional behavior to the classes generated by Castor. As an example, say, I want my Playlist class to implement an interface XYZ which has a method doXYZprocess(). If I am to modify the Playlist class to make it implement the said interface, then if I make any change to the schema file in future I’ll be in trouble. I’ll have to redo all the additions. Now this is a painful task.

An alternative was to create wrapper class around the Castor generated classes and use the wrappers instead. Well, this would work, but I wanted something smarter rather than such duplication.

This is where the third method of parsing comes into picture. It addresses the exact issue as mentioned above. The idea is to use user written classes for marshalling rather than Castor generated ones. One could write a class having lots of methods and fields, bind it to an element of an xml file and have it populated by Castor while parsing the xml. Castor provides this functionality through a Mapping.

A Mapping is another xml file which instructs Castor about the Java classes and the fields that are to be used for parsing. A great degree of freedom is provided in the writing of mapping. One could specifically tell Castor to use certain getters and setters, or leave it to Castor to populate the class fields by introspection.

An example of mapping file for the above schema file would be:

Castor interprets this mapping as the root element being plgen which would get mapped to the class Plgen. This root element can contain a list of Playlist elements. So the getter and setter that Castor calls will be

public ArrayList<Playlist> getPlaylist();

public void setPlaylist(ArrayList<Playlist>);

So our Plgen class above needs to contain these two methods. Similarly, the Playlist class needs to have the following two methods to set the extensionType field:

public String getExtensionType();

public void setExtensionType(String);

Note that I am taking the enum value as a string and will use the setter to set the Enum from a string. My getter likewise will return the Enum.toString().

If you do not want the default getters and setters to be used by Castor, then you have to specify the getter and setter as attributes of the field element in t he mapping.

Castor has compiled a help page to understand the mapping option. You may like to read it here:

Castor XML Mapping

I really liked the mapping feature. It gives me a lot of freedom to write Java classes and then use the mapping to parse any xml file into these classes. This obviates the need to understand the DOM parsing model, of iterating through the xml tree and extracting the values required. The game has been simplified to writing a mapping file and letting Castor create the java objects.

I hate xmls’ NO more. :)

Popularity: 29% [?]