You are trying to create an XML document from a Java object, and you want to customize the layout and structure of the generated XML document.
Use a Betwixt mapping file to customize the output of the BeanWriter
. Below is an example of a mapping
file for the Play
class, which was
introduced in Recipe 6.2.
When Betwixt serializes or deserializes an object to or from XML, it
will search for a resource, <classname>.betwixt
, in the same
package as the class to be written or read. The following XML
document—Play.betwixt—
is stored in
the same package as the Play
class,
and it customizes the XML output from Betwixt:
<info primitiveTypes="element"> <element name="play"> <attribute name="genre" property="genre"/> <attribute name="year" property="year"/> <attribute name="language" property="language"/> <addDefaults/> </element> </info>
This file tells Betwixt that genre
, year
, and language
shall be stored as XML attributes,
and that the remaining bean properties are to be written as XML
elements. The following code is used to create a customized XML document
from an instance of Play
:
import org.apache.commons.betwixt.io; Play play = (Play) plays.get(0); BeanWriter beanWriter = new BeanWriter( ); beanWriter.enablePrettyPrint( ); beanWriter.write( play ); logger.debug( beanWriter.toString( ) );
Betwixt creates the following XML document, which stores the
genre
, year
, and language
properties as attributes of the
play
element. The differences between
this XML document and the XML document in Recipe 6.7 are emphasized:
<play genre="tragedy" year="1603" language="english"> <author>William Shakespeare</author> <characters> <character protagonist="false"> <description>King of Denmark</description> <name>Claudius</name> </character> <character protagonist="true"> <description>Son to the late, and nephew of the present king</description> <name>Hamlet</name> </character> <character protagonist="false"> <description>friend to Hamlet</description> <name>Horatio</name> </character> </characters> <name>Hamlet</name> <summary>Prince of Denmark (Hamlet) freaks out, talks to father's ghost, and finally dies in a duel.</summary> </play>
The previous example wrote the protagonist
property of the Character
class as an attribute of the
character
element. This customization
was accomplished by putting a Character.betwixt
resource in the same
package as the Character
class.
Character.betwixt
is shown
here:
<info primitiveTypes="element"> <element name="character"> <attribute name="protagonist" property="protagonist"/> <addDefaults/> </element> </info>
In addition to customizing the structure on an XML document, a
Betwixt mapping file can also be used to change the names of elements
and attributes in an XML document. The following mapping file—another
version of Character.betwixt—
writes
the description
property of Character
as a bio
element:
<info primitiveTypes="element"> <element name="character"> <attribute name="protagonist" property="protagonist"/> <element name="bio" property="description"/> <addDefaults/> </element> </info>
In this recipe, Betwixt has wrapped all character
elements in a characters
element. If you prefer character
elements to be child elements of
play
, you can tell the XMLIntrospector
used by BeanWriter
to omit elements wrapping
collections with the following code:
import org.apache.commons.betwixt.io.BeanWriter; import org.apache.commons.betwixt.XMLIntrospector; Play play = (Play) plays.get(0); BeanWriter beanWriter = new BeanWriter( ); beanWriter.enablePrettyPrint( ); // Configure XML Introspector to omit collection elements XMLIntrospector introspector = beanWriter.getXMLIntrospector( ); introspector.setWrapCollectionsInElement(false); beanWriter.write( play ); logger.debug( beanWriter.toString( ) );
The previous code creates an XML document without the characters
element:
<play genre="tragedy" year="1603" language="english"> <author>William Shakespeare</author> <character protagonist="false"> <description>King of Denmark</description> <name>Claudius</name> </character> <character protagonist="true"> <description>Son to the late, and nephew of the present king</description> <name>Hamlet</name> </character> <character protagonist="false"> <description>friend to Hamlet</description> <name>Horatio</name> </character> <name>Hamlet</name> <summary>Prince of Denmark (Hamlet) freaks out, talks to father's ghost, and finally dies in a duel.</summary> </play>
Betwixt also allows for the customization of element and attribute
names; for example, if your class contains the property maximumSpeed
, it can be written as an
attribute named maximum-speed
or
MAXIMUM_SPEED
, using the HyphenatedNameMapper
strategy. The same
property could also be written as an element named MaximumSpeed
, using the CapitalizeNameMapper
strategy. Different
naming strategies can be used for elements and attributes by passing
instances of NameMapper
to setElementNameMapper( )
and setAttributeNameMapper( )
on an XMLIntrospector
. The following code
demonstrates the setting of both the attribute and element NameMapper
on a BeanWriter
's XMLIntrospector
:
import org.apache.commons.betwixt.io.BeanWriter; import org.apache.commons.betwixt.XMLIntrospector; import org.apache.commons.betwixt.strategy.CapitalizeNameMapper; import org.apache.commons.betwixt.strategy.HyphenatedNameMapper; BeanWriter beanWriter = new BeanWriter( ); // Set NameMappers on XMLIntrospector XMLIntrospector introspector = beanWriter.getXMLIntrospector( ); introspector.setElementNameMapper( new CapitalizeNameMapper( ) ); introspector.setAttributeNameMapper( new HyphenatedNameMapper( ) ); beanWriter.write( object );
For more information about possible customizations in Betwixt, see the "Binding Beans" section of the user guide at http://commons.apache.org/betwixt/guide/binding.html.