6.8. Customizing XML Generated from an Object

Problem

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.

Solution

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>

Discussion

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 );

See Also

For more information about possible customizations in Betwixt, see the “Binding Beans” section of the user guide at http://jakarta.apache.org/commons/betwixt/guide/binding.html.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.182.62