prev | table of contents | next |
Neither the methods of the element object factory nor the constructors
of the classes derived from the types defined in the XML schema
require that you have any of an element's child elements or
attributes at the time of the call. (The single exception is the
set of factory methods creating a JAXBElement<?>
, but their
arguments may be "empty" element objects, without any actual
XML content.) This gives you maximum freedom to design your
tree-building algorithm. Usually it will be the structure of
the input material that advocates some specific approach. Building
the document tree from comparable hierarchical structures is
the easiest way, as you can create, insert and fill the elements
as you traverse the existing structure. Sequential orderings that
correspond to one of the basic tree traversal orders can be handled
with elementary techniques. If, for instance, the data is in
post-order, you might use a stack to keep assembled XML elements
until their parent element becomes eligible for construction.
If the data isn't arranged in one of the tree traversal orders you could
set up two or more "cursors" that point into the emerging tree so that
you might add to several places in parallel.
The frequently used construction method that proceeds from the tree root towards the leaves may be written according to two typical scenarios for the construction of an element. We'll illustrate these with a skeleton layout for a product order.
<xsd:complexType name="CustomerType"> <xsd:sequence> <xsd:element name="id" type="xsd:int"/> <xsd:element name="name" type="xsd:string"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="ItemType"> <xsd:sequence> <xsd:element name="id" type="xsd:string"/> <xsd:element name="quantity" type="xsd:int"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="OrderType"> <xsd:sequence> <xsd:element name="customer" type="CustomerType"/> <xsd:element name="items" type="ItemType" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> <xsd:element name="folder"> <xsd:complexType> <xsd:sequence> <xsd:element name="orders" type="OrderType" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> </xsd:element>Assuming that we are about to add the content for a "current" element, the sequence for adding a solitary subordinate element of type X goes like this:
xElem
via a call
to factory method createX
.
current.setX( xElem )
.
xElem
via a call to
factory method createX
.
List<X>
,
with a call to the getter current.getX()
.
createX
.
List<X>
.
You should now have no problems understanding the Java code that creates an order element according to the previously given schema snippet.
// Data for an order int custId = ...; String custName = ...; Item[] items = ...; // Create order and insert in top-level document, a list of orders OrderType orderElem = objFact.createOrderType(); folder.getOrders().add( orderElem ); // Create and insert the customer element. CustomerType custElem = objFact.createCustomerType(); orderElem.setCustomer( custElem ); // Complete customer. custElem.setId( custId ); custElem.setName( custName ); // Create and add item elements. List<ItemType> itemList = orderElem.getItems(); for( Item item: items ){ ItemType itemElem = objFact.createItemType(); itemList.add( itemElem ); itemElem.setId( item.id ); itemElem.setQuantity( item.qtty ); }Another thing that can be gleaned from these lines is the danger of confusion. On the one hand, we have the classes representing XML elements, and, on the other hand, the data for the XML document is likely to be around in a more or less similar set of objects, and their classes are bound to have names that aren't entirely different from the ones coming from the schema. (In the example there is
ItemType
and Item
.)
The counter-strategy to adopt here is to enforce a rigid naming
convention which should not only deal with class names but also
include naming rules for the temporary variables referencing objects
of classes from either group.
prev | table of contents | next |