How to Unmarshal raw XML segments into arbitrary types Intended Audience Prerequisites Basic concept Mapping file References
Intended Audience
Anyone who wants to map raw XML segments into data types.
Prerequisites
None.
Basic concept
Lets say you have an XML structure:
<root>
<xmlnode attribute="misc xml data">
<data>Data 1</data>
<data>Data 2</data>
</xmlnode>
<string>Regular String Data</string>
<xmlnode2>
<misc>Misc xml to be dealt with later</misc>
</xmlnode2>
</root> |
|
And you want to save off portions of this XML in your objects, instead of
having Castor map them immediately.
package bizobj;
public class Root {
private Object anyType;
private String stringData;
private String stringXML;
public Object getAnyType() {
return anyType;
}
public void setAnyType(Object anyType) {
this.anyType = anyType;
}
public String getStringData() {
return stringData;
}
public void setStringData(String stringData) {
this.stringData = stringData;
}
public String getStringXML() {
return stringXML;
}
public void setStringXML(String stringXML) {
this.stringXML = stringXML;
}
} |
|
There are two approaches that can be used for this. The first, approach
would be to use the AnyNode type. The benefits of this approach is that
you do not have to do anything special to get the data in the mapping
file, and can both unmarshal and marshal the xml data. The drawback is
that you have to call toString() on the object to get the XML.
The second approach is to use a custom FieldHandler implementation to
convert the values. The benefit of this approach is that you are able to
convert into any type you want. The drawback is that there is currently
no way to marshal the xml data back into XML. It ends up as XML encoded
data inside the marshalled XML.
Mapping file
Here is an example mapping file that includes both examples.
<?xml version="1.0"?>
<!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN"
"http://castor.org/mapping.dtd">
<mapping>
<class name="bizobj.Root">
<field name="anyType" type="java.lang.Object">
<bind-xml name="xmlnode" node="element" />
</field>
<field name="stringData" type="string">
<bind-xml name="string" node="element" />
</field>
<field name="stringXML" type="java.lang.Object" handler="MyHandler">
<bind-xml name="xmlnode2" node="element" />
</field>
</class>
</mapping> |
|
The anyType field is set to java.lang.Object. Behind the scenes it is
actually an AnyType object.
Also, notice that the stringXML field is of type java.lang.Object. This
is because Castor looks at that first to determine what type of parsing
needs to be done, then passes it on to the Field Handler, which converts
it into whatever is desired.
Here is an example Field Handler that converts the input into a string.
import org.exolab.castor.mapping.GeneralizedFieldHandler;
public class MyHandler extends GeneralizedFieldHandler {
public Object convertUponGet(Object value) {
return (value == null) ? null : value.toString();
}
public Object convertUponSet(Object value) {
return (value == null) ? null : value.toString();
}
public Class getFieldType() { return String.class; }
} |
|
References
|