About us
Contact us
Products
Services
Articles
 Twitter    Bookmark and Share

6. JavaBeans - XML Documents Mapping

Contents | Previous Chapter | Next Chapter

This chapter describes the way bean objects are mapped to XML documents and vice-versa. In other words, it explains what XMLUtils.beanToXML() and XMLUtils.xmlToBean() do.


6.1. Bean-to-XML mapping

The beanToXML() method of XMLUtils takes a bean instance, a Hashtable that may contain mapping errors, an output stream, an optional logger object, an optional encoding ID and an optional Locale object. The values of the properties are stored in an XML document that is written to the output stream. The error table may be null or it must be a Hashtable returned by one of the mapping utilities of the framework. The error messages extracted from the error table are inserted into the XML document.

Before starting the mapping process, beanToXML() writes the prolog of the document to the output stream:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE xmlbean [
<!ELEMENT xmlbean ((bean | data | barray | darray | error)*)>
<!ELEMENT bean ((bean | data | barray | darray | error)*)>
<!ATTLIST bean name CDATA #REQUIRED>
<!ELEMENT data (error*, value?, error*)>
<!ATTLIST data name CDATA #REQUIRED>
<!ELEMENT barray ((bean | error)*)>
<!ATTLIST barray name CDATA #REQUIRED length CDATA #REQUIRED>
<!ELEMENT darray ((data | error)*)>
<!ATTLIST darray name CDATA #REQUIRED length CDATA #REQUIRED>
<!ELEMENT value (#PCDATA)>
<!ELEMENT error (#PCDATA)>
]>

The default encoding is UTF-8. You may use any character encoding supported by Java. The CharacterEncoding class defines the encoding IDs and lets you register new ones. To register a new encoding you have to provide the encoding name recognized by Java and the encoding name recognized by the XML parser.

Then, beanToXML() saves the bean data to the XML document keeping the hierarchical structure. The root element is <xmlbean>. If present, an error message is added as the character data of an <error> element.

<xmlbean>
    ...
</xmlbean>

or

<xmlbean>
    <error>errorMessage</error>
    ...
</xmlbean>

6.1.1. Mapping a standard property

For each standard property, beanToXML()

  • starts a <data> element,
  • stores the property name as the "name" attribute of the <data> element,
  • stores the error message, if present, as the character data of an <error> element,
  • stores the property value as the character data of a <value> element,
  • ends the <data> element.
<data name="propertyName">
    <value>propertyValue</value>
</data>

or

<data name="propertyName">
    <error>errorMessage</error>
    <value>propertyValue</value>
</data> 

6.1.2. Mapping a standard indexed property

For each standard indexed property, beanToXML()

  • starts a <darray> element,
  • stores the property name as the "name" attribute of the <darray> element,
  • stores the array length as the "length" attribute of the <darray> element,
  • stores the error message, if present, as the character data of an <error> element,
  • for each array element, beanToXML()
  • starts a <data> element,
  • stores the array index as the "name" attribute of the <data> element,
  • stores the error message, if present, as the character data of an <error> element,
  • stores the array value as the character data of a <value> element,
  • ends the <data> element,
  • ends the <darray> element.
<darray name="propertyName" length="N">
    <error>errorMessage</error>
    <data name="0">
        <error>errorMessage0</error>
        <value>propertyValue0</value>
    </data>
    <data name="1">
        <error>errorMessage1</error>
        <value>propertyValue1</value>
    </data>
    ...
    <data name="N">
        <error>errorMessageN</error>
        <value>propertyValueN</value>
    </data>
</darray>

Note: all or some of the <error> elements may not be present.


6.1.3. Mapping a contained data bean

For each contained data bean, beanToXML()

  • starts a <bean> element,
  • stores the property name as the "name" attribute of the <bean> element,
  • the contained bean object is passed to a recursive call of beanToXML() that will store the object's data to the XML document,
  • ends the <bean> element
<bean name="propertyName">
    ...
</bean>

or

<bean name="propertyName">
    <error>errorMessage</error>
    ...
</bean>

The <bean> element is very similar to <xmlbean>. The differences are the tag name and the presence of the "name" attribute.


6.1.4. Mapping a contained bean array

For each contained bean array, beanToXML()

  • starts a <barray> element,
  • stores the property name as the "name" attribute of the <barray> element,
  • stores the array length as the "length" attribute of the <barray> element,
  • stores the error message, if present, as the character data of an <error> element,
  • each bean object of the array is passed to a recursive call of beanToXML() that will store the object's data within a <bean> element whose "name" attribute is the array index,
  • ends the <barray> element.
<barray name="propertyName" length="N">
    <error>errorMessage</error>
    <bean name="0">
        ...
    </bean>
    <bean name="1">
        ...
    </bean>
    ...
    <bean name="N">
        ...
    </bean>
</barray>

6.2. XML-to-Bean mapping

The xmlToBean() method of XMLUtils takes an input stream, a bean object, an optional logger object, an optional encoding ID and an optional Locale object. It iterates over the properties of the bean object and tries to set them to the values encoded in the XML document that is read from the input stream. It returns a Hashtable instance that contains the errors that occurred during the mapping process or null if no error occurred.

The bean data is extracted from the <value> elements. If some of the bean properties don't have associated XML elements, the xmlToBean() method reports "missing data" errors. All user errors and application errors are collected in the error table.

The <error> tags are ignored since these are already reported errors.


6.2.1. Mapping to a standard property

For each standard property, xmlToBean()

  • gets the character data of a <value> element contained in a <data> element whose name attribute maintains the property's name,
  • tries to convert the obtained string to the property's type and
  • sets the value of the property.

If the data is missing or the conversion of the string fails then a MappingError object is added to the error table and the property is set to its default value.


6.2.2. Mapping to a standard indexed property

For each standard indexed property, xmlToBean()

  • gets the array's length from the length attribute of a <darray> element whose name attribute maintains the property's name,
  • gets the character data of the <value> elements contained in <data> elements whose name attributes maintain the array indices, (note: The <darray> element contains the <data> elements.)
  • tries to convert the obtained strings and
  • sets the values of the indexed property. (note: All these values become the elements of a new array that is stored to the indexed property using the setter method.)

Any mapping error is stored in the error table. If there are multiple errors, the error table will use a vector of MappingError objects.


6.2.3. Mapping to a contained data bean

For each contained data bean, xmlToBean()

  • creates a new instance of the contained bean by calling the no-arg constructor,
  • passes the contained bean instance to a recursive call of xmlToBean(), (note: The recursive call will operate only within a <bean> element whose name attribute maintains the name of the contained bean property - subBean.)
  • sets the subBean property of the bean object to the newly created object.

Note: All recursive calls of xmlToBean() share the same error table and use the same logger and Locale objects that are passed to the initial xmlToBean() call.


6.2.4. Mapping to a contained bean array

For each contained bean array, xmlToBean()

  • gets the array's length from the length attribute of a <barray> element whose name attribute maintains the property's name (subBeanArray),
  • creates a new array with the obtained length,
  • creates a bean instance for each array element and passes it to a recursive call of xmlToBean(), (note: The recursive calls will operate only within <bean> elements whose name attributes maintain the array indices. These <bean> elements are contained by the <barray> element.)
  • sets the subBeanArray property of the bean object to the newly created array.

6.3. Hints and Tips

One of the examples uses this mapping to implement XML-based persistence.

The XML documents created by XMLUtils.beanToXML()

  • can be converted to objects by XMLUtils.xmlToBean()
  • present the beans, contained beans and their data in a hierarchical style
  • are extensible. You may attach to each bean property additional information that is specific to your application. In this case, you'll have to update the DTD of the modified documents if the XML validation is enabled.
  • may use any character encoding supported by Java and by the XML parser.
Contents | Previous Chapter | Next Chapter

Copyright © 2000-2009 Devsphere

About us
Contact us
Products
Services
Articles