Package net.sf.practicalxml.converter.bean

This package contains classes to convert Java objects to and from XML.

See: Description

Package net.sf.practicalxml.converter.bean Description

This package contains classes to convert Java objects to and from XML. The basic structure of XML produced/consumed by these classes is similar to what you'd get from JAXB, without the requirement of annotations or schema definitions: the root element represents the object being converted, and its child nodes represent the elements/properties of the object. Complex objects have child elements, simple (primitive) objects have a single text child. Objects are processed recursively, and cycles are not detected (although this may change).

On output, the caller may specify a namespace: all elements will have this namespace. On input, namespaces are ignored: bean properties are identified by element local names. The converter will use its own namespace for any converter-specific attributes (eg, type); this namespace is defined by net.sf.practicalxml.converter.internal.ConversionStrings#NS_CONVERSION). The converter will also apply attributes from the XML Schema Instance namespace; all documentation refers to these attributes with an "xsi" prefix (eg: xsi:nil).

The most important of the converter-specific attributes is type. For primitive types, wrappers, and strings, it takes the form "xsd:TYPE", where TYPE is one of the simple types defined by XML schema. For other Java types, it takes the form "java:TYPE", where TYPE is the fully qualified Java classname.

On input, the desired type is specified by the caller or by introspection. The type attribute, if any, is used to validate whether the element matches this desired type (except in the case of collection elements, described below).

Additional conversion rules are as follows:

Java Object Type Java to XML XML to Java
Null Values By default, any field containing a null value is ignored and not written to the output. By default, any element that does not contain a Text child is treated as null, and ignored (because bean fields should already be null at construction). Optionally requires an xsi:nil attribute for values that are legally null, and throws if an empty element appears without it.
Primitives, Wrapper objects, and String By default, calls toString() on the object; optionally uses a Schema-compliant formatter (only applies to dates and floating point numbers). Uses the built-in parsers for the destination type, except where instructed to use Schema-compliant parsing.
Enums Uses the enum's name, as returned by name(). Uses the enum's valueOf method.
Arrays By default, arrays are converted using one "container" element to represent the array, and multiple children of that container to represent the elements in the array. The container element is named after the field being converted. By default, the child elements are named "data", but optionally may be named after the field or a depluralized version of the field (eg, if the field is named "widgets" the child elements may be named "widgets" or "widget" depending on options).

An alternate option is to output the array's elements directly, as repeated elements named after the field, without a "container" element (eg, if a bean has a field named "widgets" with 3 elements, then the XML produced from that bean will have three Elements named "widgets", each of which contains the data from the corresponding array element).

Elements may also be given an "index" attribute, holding their index within the array (numbered from 0). This attribute is not output by default, as its chief use is self-documenting data.

The DOM must have a "container" element; the children of this element become the elements of the array. The names of the children are ignored, as is any "index" attribute. The children are converted according to the base element type of the array.
Lists and Sets The collection is written as if it were an array (qv). Child elements are output in iterator order. The collection is processed as it if were an array (qv), with one (major) difference: since all collections inherently contain Objects, there is no type information to drive conversion. If a type attribute is present, it will be used to drive conversion. Otherwise, the element will be converted as a String (which will fail for complex types, because string conversion assumes a single text node).

Where the caller specifies an interface as the conversion class, the converter will choose an appropriate implementation class:

  • ArrayList for List or Collection
  • TreeSet for SortedSet
  • HashSet for all other Sets
Maps The map itself is represented by a "container" element, which holds one child per map entry. The map's entry-set is iterated, and children are emitted in the order of this iteration.

By default, child elements have the name "data", with an attribute "key" that contains the key used to reference the item in the map. Optionally, the map key may be used as the element name, meaning that the output of a map is indistinguishable from that of a bean. However, if this option is used, all map keys must be valid XML element names, or the converter will throw.

The converter expects a "container" element with one child per map entry. Elements are processed in sequence, which means that later elements with the same key value will overwrite earlier elements.

When processing an element, the converter first looks for an attribute named "key", and will use it as the entry key if found. Otherwise, it will use the element name. If your maps are being reduced to a single entry, look for a missing attribute.

If the type attribute is present, it will be used to drive conversion of the element. Otherwise, the element will be converted as a String (which will fail for complex types, because string conversion assumes a single text node).

Where the caller specifies an interface as the conversion class, the converter will choose an appropriate implementation class:

  • TreeMap for SortedMap
  • HashMap for all other Maps
Bean-structured Objects The object is introspected, and properties are written in the order provided by the introspector. Note that this means you can't validate beans against a schema, as the order of elements may change. The bean class must provide a no-argument constructor (otherwise it doesn't follow the bean spec, and we can't use it).

The converter relies on java.beans.Introspector to find property setter methods for an object. If the object provides multiple methods for the property, the converter will use whichever one the introspector provides.

Elements are processed in order, and the element's localname is used to find the associated object property. If the XML does not contain an element corresponding to a bean property, that property is left with its default value (ie, we don't try to find an element based on property name).

If the XML contains an element that does not correspond to any bean property, the converter will either throw or ignore the element, depending on options settings.

Other Objects not supported not supported