Skip to main content

skip to main content

developerWorks  >  Java technology | XML | Open source  >

JiBX 1.2, Part 2: XML schema to Java code

Generate cleaner, customized Java code from XML schema

developerWorks
Go to the previous pagePage 8 of 14 Go to the next page

Document options
PDF format - Fits A4 and Letter

PDF - Fits A4 and Letter
222 KB (36 pages)

Get Adobe® Reader®

Sample code


My developerWorks needs you!

Connect to your technical community


Rate this tutorial

Help us improve this content


Customizing individual components

So far, you've seen only examples of customizations that apply across the entire set of schemas, or to individual schemas. You can also customize CodeGen's handling of specific components within a schema definition, including both global definitions and items embedded within the global definitions. The customizations available include eliminating the component from the data model, changing the class or value name used for the component, and changing the schema type of the component.

Customizations to eliminate components from the data model aren't very useful if you control the schema — in that case, it's always going to be simpler to just change the schema directly. But enterprise data-exchange schemas often include specialized components that may not be appropriate for particular applications using those schemas, and these schemas are typically not under your control. Using customizations in this case allows you to simplify your data model without touching the supplied schemas.

Component customizations

Customizations for schema components work by associating a customization element with the schema-definition element representing the component. You can use several different approaches for establishing the association between the customization and the schema element because one approach may be more convenient than another in a particular situation. One part of the association is fixed, though: The name of the customization element must always match the schema component element name. So to customize an <xs:element> definition in a schema, for instance, you need to use an <element customization element (with no namespace).

Listing 15 shows a definition from one of the other schemas referenced by TimeCard, which makes a good sample to demonstrate customization of individual components. The PersonNameType consists of several simple xs:string elements, along with some other elements with complex structure. As it happens, the test documents used in the tutorial code don't include any instances of the Affix or AlternateScript elements from this type, so they're good candidates to eliminate in order to simplify the generated data model.


Listing 15. PersonName schema
<xsd:complexType name="PersonNameType">
  <xsd:sequence>
    <xsd:element name="FormattedName" type="xsd:string" minOccurs="0"/>
    <xsd:element name="LegalName" type="xsd:string" minOccurs="0"/>
    <xsd:element name="GivenName" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
    <xsd:element name="PreferredGivenName" type="xsd:string" minOccurs="0"/>
    <xsd:element name="MiddleName" type="xsd:string" minOccurs="0"/>
    <xsd:element name="FamilyName" minOccurs="0" maxOccurs="unbounded">
      <xsd:complexType>
        ...
      </xsd:complexType>
    </xsd:element>
    <xsd:element name="Affix" minOccurs="0" maxOccurs="unbounded">
      <xsd:complexType>
        ...
      </xsd:complexType>
    </xsd:element>
    <xsd:element name="AlternateScript" minOccurs="0" maxOccurs="unbounded">
      <xsd:complexType>
        ...
      </xsd:complexType>
    </xsd:element>
  </xsd:sequence>
  <xsd:attribute name="script" type="xsd:string"/>
</xsd:complexType>

Listing 16 shows one way of defining customizations to eliminate the Affix and AlternateScript elements from the data model. This approach uses a path specification, which is an XPath-like set of directions for navigating the schema definition structure. Path steps are separated by slash (/) characters, and steps matching named components of the schema definition (global type, group, or attributeGroup definitions, or element or attribute definitions whether global or not) can use an [@name=...] predicate to single out a particular instance of the component type.


Listing 16. Direct customization for unneeded components
<schema-set ...>
  <schema name="PersonName.xsd">
    <element path="complexType[@name=PersonNameType]/sequence/element[@name=Affix]"
        ignore="true"/>
    <element path=
        "complexType[@name=PersonNameType]/sequence/element[@name=AlternateScript]"
        ignore="true"/>
  </schema>
</schema-set>

In Listing 16, each path is spelled out completely, from the schema level. You can also use wildcards in the paths. The * wildcard as a path step matches any single element in the schema definition, while the ** wildcard matches any number of nested elements in the schema definition. So instead of the path complexType[@name=PersonNameType]/sequence/element[@name=Affix], you could instead use complexType[@name=PersonNameType]/*/element[@name=Affix], or complexType[@name=PersonNameType]/**/element[@name=Affix]. You couldn't use **/element[@name=Affix], though — CodeGen requires you to identify explicitly the global definition component involved in any customization as a safeguard to prevent applying the customization incorrectly.

Component customizations can be nested, as long as the nesting matches the schema-definition structure. In this case, each customization just needs to specify its target relative to the containing customization. You can also use a name="..." attribute on the customization as an alternative to a [@name=...] predicate on the final step of a path, and you can skip the element name on the final step (because it must always be the same as the name of the customization element). You can even avoid using a path completely, instead using nesting combined with a name attribute. Listing 17 shows the same customizations as Listing 16, restructured to use this alternative approach:


Listing 17. Nested customization for unneeded components
<schema-set ...>
  <schema name="PersonName.xsd">
    <complexType name="PersonNameType">
      <sequence>
        <element name="Affix" ignore="true"/>
        <element name="AlternateScript" ignore="true"/>
      </sequence>
    </complexType>
  </schema>
</schema-set>



Back to top


Simplifying the data model

Besides the PersonName components used as examples in the preceding subsection, the TimeCard schemas have a number of other complex components that are not used in the sample documents included in this tutorial. By using customizations to eliminate these unused components, you can considerably simplify the generated data model. There are also some cases where the Java value names used by CodeGen don't work well. In particular, cases where the same element name is used repeatedly can result in value names distinguished only by digit suffixes, making it difficult to understand the proper use of the values. See Listing 10 for an example, where a pair of fields named duration and duration1 are included in the generated code. You can use a customization to change one of these names to something more meaningful.

Listing 18 shows the custom3.xml file from the hrxml directory of the code, which includes all these customizations. This intentionally uses a variety of the component-identification approaches discussed in the preceding subsection, with nesting, paths, and paths mixed with names. The value-name customization is at the bottom, using a value-name="simpleDuration" attribute to change the name used for the second duration to a more descriptive form.


Listing 18. Simplifying and clarifying the TimeCard data model
<schema-set xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://ns.hr-xml.org/2007-04-15" package="org.hrxml.timecard"
    type-substitutions="xs:integer xs:int" generate-all="false">
  <name-converter strip-suffixes="Type"/>
  <class-decorator class="org.jibx.schema.codegen.extend.CollectionMethodsDecorator"/>
  <schema name="UserArea.xsd" excludes="UserArea UserAreaType"/>
  <schema name="PersonName.xsd">
    <complexType name="PersonNameType">
      <sequence>
        <element name="Affix" ignore="true"/>
        <element name="AlternateScript" ignore="true"/>
      </sequence>
    </complexType>
  </schema>
  <schema name="TimeCard.xsd" includes="TimeCard">
    <complexType name="TimeCardType">
      <element path="**/element[@name=Allowance]" ignore="true"/>
      <element path="**/element[@name=PieceWork]" ignore="true"/>
      <element path="**/element[@name=TimeEvent]/**/" name="RateOrAmount" ignore="true"/>
      <element path="**/choice/[@name=Duration]" value-name="simpleDuration"/>
    </complexType>
  </schema>
</schema-set>

You can use the custgen3 Ant target to try this customization with CodeGen, or use the custom3 target to run the complete sequence of generate, compile, bind, and test. The customizations reduce the generated class count to 9 top-level classes and 10 inner classes, for a total of 19. This count is exactly half the number of classes in the original data model generated without using customizations.



Back to top



Go to the previous pagePage 8 of 14 Go to the next page