Groups

In XSD, a group is a container for particles. Each particle may be an element, an element wildcard, or another group.

If a complex type has a group for its content model, then the properties that are generated for the complex type are derived from the particles in the group.

Representation of a Single Element

A single element is represented using some type T. If the element's type is a simple type, then Tis determined as described in the section XSD Simple Type Mappings. If the element's type is a complex type, then Tis a generated type, as described in this section, XSD Complex Type Mappings.

Representation of Element Wildcard

A single replacement for an element wildcard is represented using a String. The contents of the String will be raw XML (including character escaping).

The properties for element wildcards are named "any", "any_1", "any_2" etc..

Example XSD:

   <xsd:complexType name="MyType">
      <xsd:sequence maxOccurs="unbounded">
         <xsd:any namespace="##any"/>
         <xsd:any namespace="##other"/>
      </xsd:sequence>
   </xsd:complexType>

C# and Java:

{
   public String getAny() {...}

   public boolean isSetAny() {...}

   public void setAny(String value) {...}

   public String getAny_1() {...}

   public boolean isSetAny_1() {...}

   public void setAny_1(String value) {...}

   ...
}

In this example, a group class (MyType_1) is generated to represent the repeating sequence group. The methods shown are the property methods for the two element wildcards.

  MyType_1 myType = new MyType1();
 
myType.setAny("<room><closet>space&gt;20</closet></room>");

The value must begin with an element start tag, and XBinder will validate that the namespace of that element is valid according to the <xsd:any> namespace attribute.

If the XML includes namespace prefixes, use the addNamespace method on the complex type class to ensure that the namespace will be encoded with the desired prefix. See Controlling XML Namespaces for encoding.

Representation of a Group

The group may be a reference to a named group, or it may be an unnamed, nested group. Either way, XBinder will generate a class for it (see Group Classes).

A named group results in a class of similar name, with a suffix of "_Group" appended (this avoids name clashes with classes created for types).

A nested group is named based on the type under which it is ultimately nested. The name is of the form ComplexType_S, where S is a sequence number based on the location of the group relative in the overall construct.

Example XSD:

   <xsd:group name="MyGroup">
      <xsd:sequence>
         <xsd:element name="elem1" type="xsd:string"/>
         <xsd:element name="elem2" type="xsd:string"/>
         <xsd:sequence maxOccurs="3">
            <xsd:element name="elem3" type="xsd:string"/>
            <xsd:element name="elem4" type="xsd:string"/>
         </xsd:sequence>
       </xsd:sequence>
   </xsd:group>

This XSD will result in a group class named MyGroup_Group (representing class MyGroup), and in a group class named MyGroup_Group_3 (representing the nested sequence group). The suffix is 3 because the nested sequence is the third item within the enclosing sequence. Had the nested sequence been placed directly after elem1 instead of elem2, then the suffix would have been 2.

Generating Properties for Particles

Let Tbe the type to represent a single occurrence of a particle, as just described above for elements, element wildcards, and groups.

If the particle does not repeat, we will have an atomic property of type T.

If the particle does repeat, we will have either an indexed property or a list property, of type T(that is, List/IList< T> or T[]). If the particle has maxOccurs > 100 or maxOccurs = unbounded, a list property is used; otherwise, an indexed property is used.

Tmay itself be a single-dimensional array type, so that the particle may be a two dimensional array. This will occur, for example, if you have a repeating element of a list type.

Sequence, All, and Choice Groups

XSD defines three kinds of groups that particles may belong to: sequence, all, and choice. Each of the particles in a group are modeled as just described in Generating Properties for Particles. However, the kind of group in which particles appear also affects the code that is generated.

An < xsd:sequence> group fixes the order in which the particles must appear. This is handled by the encode/decode methods. Similarly, an <xsd:all> group requires each of the particles to appear, but they may appear in any order. This is again handled by the encode/decode methods.

An < xsd:choice> group specifies a number of particles, any one of which may appear. In this case, XBinder generates an extra property that indicates which of the choices has been made.

Example choice group:

   <xsd:complexType name="MyChoiceType">
      <xsd:choice>
         <xsd:element name="choice1" type="..."/>
         ...
         <xsd:element name="choiceN" type="..."/>
      </xsd:choice>
   </xsd:complexType>

Abbreviated generated code:

Java:

   public class MyChoiceType extends XBComplexType
   {
      ...
      public enum Choice  {
         choice1, choice2, ..., choiceN}
      ...
      //content methods

      public int getChoice1() {...}

      public boolean isSetChoice1() {...}

      public void setChoice1(int value) {...}

      public void setChoice1() {...}
      ...
      public Choice getWhichField() {...}
   }

C#:

   public class MyChoiceType : XBComplexType
   {
      ...
      public enum Choice  {
         None, 
         choice1, 
         choice2, ..., 
         choiceN
      }
                  
      ...

      //content methods

      public int getChoice1() {...}

      public bool isSetChoice1() {...}

      public void setChoice1(int value) {...}

      public void setChoice1() {...}
      ...
      public Choice getWhichField() {...}
   }

Note the following features:

  1. The usual property methods are generated for each of the particles in the choice group. However, since each particle is essentially optional, there will be an isSet method for every particle.

  2. You may determine which field is set either by using one of the isSet methods, or by using the getWhichField method.

  3. Setting the property for a particle automatically selects that particle as the chosen one.

Representation of Mixed Content

A "mixed" content model is represented as a single String of raw XML (ie, as it would appear in the XML file). The AnyTypeclass is an example of what is generated for mixed content models (see the section called “anyType”).

When decoding mixed content, the events received by XBinder from the XML parser must be encoded back into XML, so that a string of XML can be made available to you, the programmer. As a result, in some cases, you will not see the exact, original XML. For example (admittedly a strange scenario), the original XML may have encoded the 'A' character using a character reference of "&#x41;" but since the character 'A' can be encoded as itself (unlike, for example, the '&' character), you will see it as an 'A' character.

When encoding mixed content, XBinder writes out the mixed content string exactly as-is. You must handle any character escaping yourself. For example, if you wish to encode a literal '<' character in some text, you must encode it as "&lt;". If you are embedding namespace prefixes, you will want to be sure the prefix you use is mapped to the correct namespace. To declare these namespaces on the parent element, use method XBComplexType.addNamespace(nsUri, prefix). Otherwise, you may embed a namespace declaration in your mixed content string.

Mixed content handling can be turned off using the -nomixed command line option. In that case, XBinder compiles your schema as though it were first modified to have all mixed content models changed to non-mixed. Therefore, any instances you decode must be valid according to this imaginary, modified version of your schema, or else a validation error results.