MaxOccurs Attribute Binding Support
The .NET Framework provides partial binding support for the maxOccurs attribute.
For most elements that may specify a maxOccurs attribute, Xsd.exe interprets a value of 0
as 1
, producing a non-array field, and a value greater than 1 as unbounded
, producing an array field. The behavior varies between elements.
Explanation
The maxOccurs and minOccurs attributes constrain how many times in succession the specified entity can appear in the corresponding position in an XML instance document.
These attributes appear only within complex type definitions. Therefore, for an <element> or <group> element to have these attributes, the element must be a local declaration or a reference to a global declaration, not the global declaration itself.
For binding classes with XML Schema complex types, the .NET Framework does not provide a direct programming language equivalent to the maxOccurs or minOccurs attribute.
When generating source code from an XML Schema document or performing the reverse translation, Xsd.exe interprets the maxOccurs attribute differently based on the XML Schema definition language element in which it appears. The following table explains the interpretations by element:
Element | Interpretation |
---|---|
<element> |
Possible values:
|
<group> |
For the <group> element, a maxOccurs value of However, by default Xsd.exe treats a To properly import schemas containing groups with maxOccurs greater than |
<all> |
Any value for the maxOccurs attribute other than |
<any> |
Possible values
|
<choice> |
The <choice> element contains two or more child elements, each representing an element or group of elements. It indicates that, in a given instance document, only one of those entities can appear in the specified position. The choices must differ by element name; optionally, they differ by type and, for a group, by number. For more information, see the <choice> element. For the <choice> element, as for the <element> and <any> elements, a maxOccurs value of For a value of For a value of |
<sequence> |
For the <sequence> element, as for most of the preceding elements, a maxOccurs value of However, Xsd.exe treats a XmlElementAttribute attributes applied, one for each element in the group. The type of the array is determined by the types of the elements – the type will be the derived-most type that all elements can be assigned to. That is, if a group contains elements of types Type1 and Type2 that both derive from TypeBase, the array will be of type TypeBase. If there is no common base type, the array will be of type Object. For a related example, see the <sequence> example at the bottom of this topic. |
When generating an XML Schema document from a set of classes in an assembly, Xsd.exe reverses the preceding conversions, producing a maxOccurs value of 1
from a single instance and a maxOccurs value of unbounded
from an array.
While Xsd.exe binds a maxOccurs value of unbounded
to an array, it binds a maxOccurs value of 1
to the designated parent element, if any, of an array.
A schema data type, with a name that begins with ArrayOf, is created to represent the array's parent element if the default System.Xml.Serialization.XmlArrayAttribute is applied to the array. If an System.Xml.Serialization.XmlElementAttribute instead is applied to an array, the array elements appear in an instance document as children of the element that binds to the class. For more information on array bindings, see Controlling XML Serialization Using Attributes.
More on array bindings. To understand the translation of a value greater than 1 to an array, consider the difference between declaring an object of a certain type and assigning a value (literally a memory location in the stack or the heap) to that object. Start with the following XSD element:
<xsd:element minOccurs="5" maxOccurs="5" name="items" type="xsd:token" />
Manually writing code, you would not express the array size of five in the type declaration, which would be: public string[] items
. Instead you would express the array size when assigning a value: items = new string[5]
.
The only kinds of source code Xsd.exe produces from an XML schema are type and field declarations and metadata that can be applied to types and fields as attributes. Assigning values to objects extends beyond that scope.
The place to enforce a value greater than 1 is by validating an XML document with the XmlValidatingReader class against an XML Schema document represented by the Schema Object Model (SOM). The SOM uses the XmlSchemaParticle.MaxOccurs and XmlSchemaParticle.MaxOccursString properties, both of which apply to all elements that can contain a maxOccurs attribute.
Example
Input XML schema <choice> element found within a complex type definition:
<xsd:choice maxOccurs="unbounded">
<xsd:element name="stringA" type="xsd:string"/>
<xsd:element name="stringB" type="xsd:string"/>
</xsd:choice>
Relevant passages from the C# class generated from the preceding XML Schema document, plus the enumeration representing the element choices, (assuming a target namespace of http://example.org/):
[System.Xml.Serialization.XmlElementAttribute("stringA", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("stringB", typeof(string))]
[System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemsElementName")]
public string[] Items;
[System.Xml.Serialization.XmlElementAttribute("ItemsElementName")]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public ItemsChoiceType[] ItemsElementName;
...
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://example.org/", IncludeInSchema=false)]
public enum ItemsChoiceType {
stringA,
stringB,
}
The complex type generated from a class compiled from the preceding C# source code is effectively equivalent to the original complex type.
<sequence>
Example
Input XML Schema document containing a sequence with maxOccurs greater than1
:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://example.org/" targetNamespace="http://example.org/" elementFormDefault="qualified">
<xsd:element name="ComplexInstance">
<xsd:complexType>
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="Field1" type="xsd:token"/>
<xsd:element name="Field2" type="xsd:int" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
C# class generated from the preceding XML Schema document without any command line options:
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://example.org/")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://example.org/", IsNullable=false)]
public class ComplexInstance {
[System.Xml.Serialization.XmlElementAttribute("Field1", DataType="token")]
public string[] Field1;
[System.Xml.Serialization.XmlElementAttribute("Field2")]
public int[] Field2;
}
XML Schema complex type generated from an assembly compiled from the preceding C# source:
<xs:complexType name="ComplexInstance">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="Field1" type="xs:token" />
<xs:element minOccurs="0" maxOccurs="unbounded" name="Field2" type="xs:int" />
</xs:sequence>
</xs:complexType>
As you can see, the resulting schema is not equivalent to the original schema. To properly import a schema having sequences with maxOccurs greater than1
, use the /order command line option, resulting in the following:
[System.Xml.Serialization.XmlTypeAttribute
(Namespace="http://example.org/")]
[System.Xml.Serialization.XmlRootAttribute
(Namespace="http://example.org/", IsNullable=false)]
public partial class ComplexInstance
{
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute
("Field1", typeof(string), DataType="token", Order=0)]
[System.Xml.Serialization.XmlElementAttribute("Field2",
typeof(int), Order=0)]
public object[] Items;
}
Possible containing elements: <all>, <any>, <choice>, <element>, <group>, <sequence>
See Also
Reference
XmlSchemaParticle.MaxOccurs
XmlSchemaParticle.MaxOccursString
XmlSchemaAll
XmlSchemaAny
XmlSchemaChoice
XmlSchemaElement
XmlSchemaGroupRef
XmlSchemaSequence