Although packaged with the Send Fax library, the XMLBuilder is a standalone tool used to converts a java beans graph (the model) into an xml document.
The builder exposes two basic methods: one to map the model to an xml document (a DOM tree) and the other to save the xml document.
// Step
1: create document (DOM tree)
XMLBuilder
builder = new XMLBuilder();
/* Namespace handling defaults to false.
If true, the meta-document must declare
the namespace URI http://xml.utility/XMLBuilder
on its root element and all
meta-attributes must be qualified.
Example: <root
xmlns="http://fax.server.com/" xmlns:xmb="http://xml.utility/XMLBuilder">
<child xmb:property="..." .../>
. . .
</root>
*/
builder.setNameSpaceAware(true);
File f = new
File(metatDocPath);
FileInputStream fis = new FileInputStream(f);
Document doc
= builder.createDocument(faxModel, fis);
// Step 2: save document
Properties
props = new Properties();
props.put(OutputKeys.METHOD, "xml");
props.put(OutputKeys.ENCODING, "ISO-8859-1");
props.put(OutputKeys.INDENT, "yes");
f = new
File(docPath);
builder.saveDocument(doc, new FileOutputStream(f), props);
To create the DOM tree from the model, the XMLBuilder uses a meta-document (e.g. GatewayMetaDoc). The meta-document is an XML skeleton of the document to be produced by the XMLBuilder. Meta-document elements may have meta-attributes the XML builder uses to produce the DOM tree.
The meta-attributes supported are specified by the processing
instruction: <?meta-att-list value="property index
childIsText skip default"?>

When parsing the meta-document, this attribute instructs the builder to map the current element with a property from the model.
In the following example, the builder will map the recipient-list element with the model property: recipientList.
<recipient-list property="recipientList">
In this example, the property recipientList must be a first-level child of the model.
To map a model property that is not a first level child, the property name must be nested, as in:
<first-name
property="senderInfo.firstName" childIsText="true"/>
In the above example, the builder will map the element first-name with the property firstName of the senderInfo bean.
Although not fully tested, the builder should support any other property name format described in the PropertyUtilsBean class, with a little variation for indexed property name.
Remarks:
To map a model list to a DOM node list, the builder expects a corresponding meta-document list element with only one occurrence, which will be used as a skeleton for the list content to be produced.
<recipient-list
property="recipientList">
<Recipient>
<fax
property="recipientList[{0}].faxNumber" index="0"
childIsText="true"/>
<title
property="recipientList[{0}].title" index="0"
childIsText="true" skip="true"/>
<first-name property="recipientList[{0}].name"
index="0" childIsText="true"/>
<company property="recipientList[{0}].company"
index="0" childIsText="true"/>
</Recipient>
</recipient-list>
In the above example, the recipient-list element is mapped to the model property: recipientList.
When parsing this element, the builder determines the model property is in fact a java.util.List and expects the element to have only one child: (the <Recipient> element). The builder will create a <Recipient> element for each entry of recipientList.
The recipient element children are mapped to the recipientList entries using the indexed and nested property name format: recipientList[{0}].propertyName. The list index must be {0} (not [0]), because the builder uses the MessageFormat api, to replace {0} with the current value of the index meta-attribute. In a meta-document, the index attribute value must always be set to zero. The builder increments the value of the index attribute when iterating over a model list property.
Remarks:
When an element has this meta-attribute, the builder creates a child text node for the element. The text node value is the model property value.
Example:
If the model property senderInfo.firstName is Bob, the builder will produce the element: <first-name>Bob</first-name> when parsing the meta-document element: <first-name property="senderInfo.firstName" childIsText="true"/>. It should be noted that setting childIsText to false would produce the empty element: <first-name/>.
Remarks:
When the builder parses a meta-document element that has this attribute set to true, it will not create a node for that element.
Example:
Because the attribute skip is set to true, the title element will not be render in the output document.
<title property="recipientList[{0}].title" index="0" childIsText="true" skip="true"/>
Remarks:
This meta-attribute can be set on a meta-document element that is mandatory in the document to be created and for which the model has no corresponding property.
Remarks:
The user is responsible to properly combined meta-attributes and to apply them where it makes sense (terminal vs. non-terminal elements). Otherwise, the document produced by the builder could be invalid according to its dtd or schema. The builder does not attempt to validate the mixtures or the meta-document.
The following table summarizes what the builder expects as mixtures and on which element (terminal or non-terminal) they could be applied.
|
|
Mixture |
Outcome |
|
1. |
<element> |
The builder adds the node <element> to the DOM tree. |
|
2. |
<element skip=true> |
The builder ignores the element (and its children) |
|
3. |
<element skip=false> |
The builder adds the node <element> to the DOM tree. |
|
4. |
<element default=abc/> |
The builder adds the nodes <element>abc</element> to the DOM tree. |
|
5. |
<element property=prop> |
If the builder is unable to retrieve prop from the
model for any reasons, it will throw an exception and stop parsing the
meta-document. if prop is null or is an empty list, the builder skips <element> and its children nodes. Otherwise, the builder adds the node <element> to the DOM tree. |
|
6. |
<element property=prop childIsText=true/> |
If the builder is unable to retrieve prop from the model for any reasons, it will throw an exception and stop parsing the meta-document. if prop is null or is an empty list, the builder skips <element>. Otherwise it invokes the toString() method on prop and adds the nodes <element>prop.toString()</element> to the DOM tree. |
|
7. |
<element property=prop childIsText=false/> |
If the builder is unable to retrieve prop from the model for any reasons, it will throw an exception and stop parsing the meta-document. if prop is null, the builder skips <element>. Otherwise, the builder adds the nodes <element/> to the DOM tree. |
|
8. |
<element property=prop childIsText=true skip=true/> |
If the builder is unable to retrieve prop from the model for any reasons or prop is null, the builder will skip <element>. Otherwise, the builder adds the node <element>prop.toString()</element> to the DOM tree. |
|
9. |
<element property=prop childIsText=true skip=false/> <element property=prop childIsText=false skip=false/> |
See 6. See 7. |
|
10. |
<element property=list[{0}].prop index=0 childIsText=true/> |
If the builder is unable to retrieve list[index].prop from the model for any reasons, it will throw an exception and stop parsing the meta-document. if list[index].prop is null, the builder skips <element>. Otherwise, the builder adds the nodes <element>list[index].prop.toString()</element> to the DOM tree. |
|
11. |
<element property=list[{0}].prop index=0 childIsText=false/> |
See 7. |
|
12. |
<element property=list[{0}].prop index=0 childIsText=true skip=false/> <element property=list[{0}].prop index=0 childIsText=true skip=true/> |
See 10. See 8. |
|
13. |
<element property=prop skip=true> <child> </element> |
If the builder is unable to retrieve prop from the model for any reasons, or prop is null or is an empty list, the builder will skip <element> and its children. Otherwise, the builder adds the node <element> to the DOM tree. |
|
14. |
<element property=prop skip=false> <child> </element> |
See 5. |
|
15. |
<element property=prop/> |
If the builder is unable to retrieve prop from the model for any reasons, it will throw an exception and stop parsing the meta-document. if prop is null, the builder will skip <element>. Otherwise, the builder adds the node <element> to the DOM tree. |
|
16. |
<element property=prop skip=true/> |
If the builder is unable to retrieve prop from the model for any reasons or prop is null, the builder will skip <element>. Otherwise, the builder adds the node <element> to the DOM tree. |
|
17. |
<element property=prop skip=false/> |
See 15. |
|
18. |
<element property=prop default=abc/> |
If the builder is unable to retrieve prop from the model for any reasons or prop is null, the builder will add the nodes <element>abc</element> to the DOM tree. |
|
19. |
<element property=prop childIsText=true default=abc/> |
If the builder is unable to retrieve prop from the model for any reasons or prop is null, the builder will add the nodes <element>abc</element> to the DOM tree. Otherwise, the builder adds the node <element>prop.toString()</element> to the DOM tree. |
|
20. |
<element property=prop childIsText=false default=abc/> |
If the builder is unable to retrieve prop from the model for any reasons or prop is null, the builder will add the nodes <element>abc</element> to the DOM tree. Otherwise, the builder adds the node <element/> to the DOM tree. |
The XMLbuilder tool has been developed and tested with JDK 1.4.2_05
The following libraries are needed in your CLASSPATH:
org.apache.common.beanutils 1.6.1
org.apache.common.collections 2.1.1
org.apache.common.logging 1.0.4
The builder has not been tested with lower or higher version of these librairies.
The XMLBuilder javadoc is available here.