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.
