Home of: [Atelier "FUJIGURUMA"] >> [SASAX hosted by SourceForge.net]

SEE "For Readers of English Version",
or Japanese version of this page

Element choice

This section explains how to parse runtime determined element in XML document with SASAX.

Define document structure

Schema in XML Schema and sample of document is shown in "Document structure".

Schema in XML Schema:

<xs:schema 
  targetNamespace="http://www.lares.dti.ne.jp/~foozy/"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:local="http://www.lares.dti.ne.jp/~foozy/">

  <xs:simpleType name="int">
    <xs:restriction base="xs:integer"/>
  </xs:simpleType>

  <xs:simpleType name="string">
    <xs:restriction base="xs:token"/>
  </xs:simpleType>

  <xs:element name="envelope">
    <xs:complexType>
      <xs:choice>
        <xs:element name="int" type="local:int"
          form="qualified"/>
        <xs:element name="string" type="local:string"
          form="qualified"/>
      </xs:choice>
    </xs:complexType>
  </xs:element>
</xs:schema>

Sample - "int" case:

<foozy:envelope
 xmlns:foozy="http://www.lares.dti.ne.jp/~foozy/">
  <foozy:int>
    12245678
  </foozy:int>
</foozy:envelope>

Sample - "string" case:

<foozy:envelope
 xmlns:foozy="http://www.lares.dti.ne.jp/~foozy/">
  <foozy:string>
      text message
  </foozy:string>
</foozy:envelope>

Document structure

You can know below things about target document.

Define factory class(es)

To handle element(s) choosen at runtime, you should define factory class for them as shown in "Define factory class".


public class IntElementFactory
    implements ElementFactory //
{
    final static private String URI =
        "http://www.lares.dti.ne.jp/~foozy/";

    final static private String NAME = "int";

    final static private NameChecker CHECKER =
        new NameChecker(URI, NAME);

    ////////////////////////////////////////
    // Implementation of interface ElementFactory

    public boolean accepts(ParseContext context,
                           String uri,
                           String lName)
    {
        return CHECKER.accepts(uri, lName);
    }

    public Element create(Element parent){
        return new IntElement(parent, URI, NAME);
    }
}

Define factory class

"IntElementFactory" examines whether specified name is acceptable (in "accepts()" method). "NameChecker" is utility class to examine equality of name.

And factory class creates element object under specified parent (in "create()" method).

Factory for "string" element is also defined as same as IntElementFactory.

Create element object(s)

Objects to parse the document described in the former are created as shown in "Element object(s) creation".


CompositeElement envelopeElement =
    new CompositeElement(null, uri, "envelope");

ElementChoice choice =
    new ElementChoice(envelopeElement);

envelopeElement.addMustItem(choice);

Element object(s) creation

But ElementChoice is not usefull by itself. You must register factories as shown "Registration of factories".


choice.add(new IntElementFactory());
choice.add(new StringElementFactory());

Registration of factories

Now specified factories are registered as one for candiate element.

Parse document

You can parse XML document by the code shown in "Parse document".


ElementDrivenHandler handler =
    new ElementDrivenHandler(envelopeElement);

handler.parse(reader);

Element determined = choice.getDetermined();

Parse document

After parsing XML document, you can get determined element by getDetermined() method of ElementChoice.

You can idenitfy what element is determined both by invoke accepts() method on gotten element, and by "instanceof" examination. But using accepts() method is recommended for performance efficiency.

Complete code for this tutorial section is jp.ne.dti.lares.foozy.sasax.ChoiceDemo under src/demo/sasax/src in distribution. This class is included in demo.jar of binary distribution.


To next section "Custom validation"

Detailed information

Class diagram

Class diagram in this section is shown below:

Class diagram
Class diagram (click for large figure)

Object diagram

Object diagram in this section is shown below:

Object diagram
Object diagram (click for large figure)

Sequence diagram

Processing flow between ElementDrivenHandler, ElementChoice, ElementFactory implementation class and Element created by ElementFactory is shown as below:

  1. ElementDrivenHandler invokes "startElement" on ElementChoice
  2. ElementChoice invokes "create" on ElementFactory(IntElementFactory now)
  3. IntElementFactory returns created Element(IntElement now)
  4. ElementChoice delegates "startElement" to returned Element(IntElement now)
  5. IntElement returns inself as next event receiver
  6. ElementDrivenHandler holds "intElement" as next event receiver
  7. ElementDrivenHandler invokes methods on "intElement"
  8. .....
  9. ElementDrivenHandler invokes "endElement" on IntElement
  10. IntElement returns Element specified at construction time as next event receiver

And sequence diagram is shown below.

Sequence diagram
Sequence diagram (click for large figure)

Class names

In this tutorial, abbreviated class names are used. Complete names are shown below.

NotationFull name
CompositeElement jp.ne.dti.lares.foozy.sasax.CompositeElement
Element jp.ne.dti.lares.foozy.sasax.Element
ElementChoice jp.ne.dti.lares.foozy.sasax.ElementChoice
ElementDrivenHandler jp.ne.dti.lares.foozy.sasax.ElementDrivenHandler
ElementFactory jp.ne.dti.lares.foozy.sasax.ElementFactory
NameChecker jp.ne.dti.lares.foozy.sasax.NameChecker
ParseContext jp.ne.dti.lares.foozy.sasax.ParseContext
IntElement jp.ne.dti.lares.foozy.sasax.IntElement