Mapping documentation - mamift/LinqToXsdCore GitHub Wiki

LINQ to XSD Mapping Documentation

Who should read this?

The following document systematically describes the mapping of XML schemas to .NET object models. The normal user of the LINQ to XSD technology is not necessarily assumed to work with this documentation. The idea is that the implemented mapping is mostly intuitive and that intellisense and object browsing provide sufficient help for the developer. The documentation mainly serves as an informal specification.

Notational conventions for OO APIs

The resulting .NET classes are described in C#-like pseudo code so as to hide routine technicalities.

All shown classes and members are implicitly public.

  • Hence, the keyword public is universally omitted.
  • Constructors are marked by the keyword constructor -- for clarity.
  • We are not using C#'s verbose notation "static explicit operator".
  • Instead we use the short notation explicit cast.
  • We elide the implementations of all property members.
  • To this end, we use "interface notation": { get; set; }.

OO API (Illustration of notation)

class Foo : XTypedElement
{
   	constructor Foo();
   	explicit cast Foo(System.Xml.Linq.XElement xe);
   	property string Bar	{ get; set; }
}

Table of contents

Global types and elements

Subsections

Further reading

  • XSD's forms of element and type substitution are discussed separately.
  • Some other abstraction forms such as attribute declarations are mapped trivially.

Complex-type definitions

Complex-type definitions are mapped to classes.Each generated class comprises the following members:

  • a default constructor;
  • an explicit cast from XElement to the defined class;
  • some inherited API members such as Save; see the LINQ to XSD manual;
  • further members depending on the content model. The class that is generated for a complex type subclasses XTypedElement. In fact, a derived complex-type is mapped to a subclass of the class that is generated for its base type.

Schema sample (Complex-type definitions)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <!-- A complex type for addresses -->
     <xs:complexType name="Address">
          <!-- address details omitted -->
     </xs:complexType>
</xs:schema>

OO API

class Address : XTypedElement
{
   	constructor Address();
   	explicit cast Address(System.Xml.Linq.XElement xe);
}

Roots with anonymous, complex types

We use the term "root" to refer to global element declarations in an XML schema.

We recall that a valid instance must be necessarily rooted in an element of that kind.

Such roots are essentially mapped in the same way as complex-type definitions.

Schema sample (Roots with anonymous, complex types)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <!-- A global element declaration for addresses -->
     <xs:element name="Address">
          <xs:complexType>
               <!-- address details omitted -->
          </xs:complexType>
     </xs:element>
</xs:schema>

OO API

class Address : XTypedElement
{
   	constructor	  	Address();
   	explicit cast	  	Address(System.Xml.Linq.XElement xe);
}

The conceptual difference between complex-type definitions and root element declarations is worth recalling: The latter define proper types in the sense of sets of elements, whereas the former model "incomplete" elements because element tags are not prescribed. This conceptual difference is reflected in the behavior of the generated object types. That is, the complex-type name serves as "preliminary" element tag for any instance of the class that corresponds to the complex type in question; this preliminary tag is eventually resolved to a proper element tag, when the instance is parented or when it is wrapped in a root element.

Note: Save and Load members are potentially misleading for classes that were generated from complex-type definitions since de-/serialization is only well-defined for root-element declarations. It is conceivable that a future release of LINQ to XSD makes explicit the conceptual difference between complex-type definitions and root element declarations.

Roots with type references to complex types

This pattern makes combined use of a complex-type definition and a global element declaration.

Schema sample (Roots with type references to complex types)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <xs:element name="BillTo" type="Address"/>
     <xs:element name="ShipTo" type="Address"/>
     <xs:complexType name="Address">
          <xs:sequence>
               <xs:element name="Name" type="xs:string"/>
               <!-- ... -->
          </xs:sequence>
     </xs:complexType>
</xs:schema>

This style is mapped as follows:

  • The following classes are generated in this case:
    • There is one class for each element declaration ("the envelope").
    • There is one class for each complex type ("the content").
  • Envelopes can be constructed from content by means of a non-default constructor.
  • The content can be extracted from the envelope by means of the Content member.
  • The "envelope" class implements the API of the "content" class by forwarding.

OO API (Roots with type references to complex types)

class Address : XTypedElement
{
   	constructor	  	Address();
   	explicit cast	  	Address(System.Xml.Linq.XElement xe);
   	property	  	string	  	Name	  	{ get; set; }
}
class BillTo : XTypedElement
{
   	constructor	  	BillTo();
   	constructor	  	BillTo(Address content);
   	explicit cast	  	BillTo(System.Xml.Linq.XElement xe);
   	property	  	Address	  	Content	  	{ get;  }
   	property	  	string	  	Name	  	{ get; set; }
}
class ShipTo : XTypedElement
{
   	constructor	  	ShipTo();
   	constructor	  	ShipTo(Address content);
   	explicit cast	  	ShipTo(System.Xml.Linq.XElement xe);
   	property	  	Address	  	Content	  	{ get;  }
   	property	  	string	  	Name	  	{ get; set; }
}

The combined use of element declarations and complex-type definitions leads to potentially convoluted object models, when the most direct mapping is applied. Hence, this usage pattern of XSD may suggest schema normalizations. Note: The current release of LINQ to XSD does not yet provide any relevant schema normalization.

Simple-type definitions

Schema sample (Simple-type definitions)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <xs:simpleType name="Month">
          <xs:restriction base="xs:token">
               <!-- restriction facets omitted -->
          </xs:restriction>
     </xs:simpleType>
</xs:schema>

By default, simple-type definitions are not mapped to any class that the programmer is supposed to instantiate.

Note: The current release of LINQ to XSD generates a vacuous class for each simple-type definition. This class should be omitted. By customization, one can also request a class that is designated to a simple-type definition.

Note: This option not supported by the current release of LINQ to XSD. The use of designated classes offers two benefits: (i) simple-type names from the XML schema can be used in program code; (ii) substitutability for simple types (say, subtyping in OO terms) can be precisely expressed.

Roots with anonymous, simple types

Root element declarations (with anonymous types or not) are mapped to classes.

Schema sample (Roots with anonymous, simple types)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <xs:element name="Month">
          <xs:simpleType>
               <xs:restriction base="xs:string">
                    <!-- restriction facets omitted -->
               </xs:restriction>
          </xs:simpleType>
     </xs:element>
</xs:schema>

OO API

class Month : XTypedElement
{
   	constructor	  	Month();
   	explicit cast	  	Month(System.Xml.Linq.XElement xe);
   	property	  	string	  	TypedValue	  	{ get; set; }
}

The (simple) content of such root elements can be access with a designated TypedValue property (akin to LINQ to XML's untyped value property). The type of this property is the built-in base type of the anonymous simple type. As usual, the class also provides an explicit coercion (cast) from XElement to the class.

Roots with type references to simple types

Schema sample (Roots with type references to simple types)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <xs:element name="Month" type="MonthType"/>
     <xs:simpleType name="MonthType">
          <xs:restriction base="xs:string">
               <!-- restriction facets omitted -->
          </xs:restriction>
     </xs:simpleType>
</xs:schema>

OO API

class Month : XTypedElement
{
   	constructor	  	Month();
   	constructor	  	Month(string content);
   	explicit cast	  	Month(System.Xml.Linq.XElement xe);
   	property	  	string	  	TypedValue	  	{ get; set; }
}

The (simple) content of such root elements can be access with a designated TypedValue property (akin to LINQ to XML's untyped value property). The type of this property is the OO counterpart for the built-in XSD base type of the referenced simple type. As usual, the class also provides an explicit coercion (cast) from XElement to the class.

Content models

Subsections

Executive summary

  • Element particles are mapped to properties.
  • Properties exhibit an XPath-like semantics for the child axis.
  • Sequence groups map to a group of properties for their element particles.
  • Choices are mapped like sequences + mutual exclusion semantics.
  • Optionality is modeled with null or nullable.
  • Repetition is modeled with IList.
  • Element-name recurrence maps to single properties.
  • The nesting of content models is not directly exhibited by the resulting API.
  • The API for nested content models is limited in terms of construction and updates.
  • Local element declarations of an anonymous types imply a nested class.
  • Element and attribute wildcards are mapped to special properties.

Flat sequences

Characteristics of flat sequences:

  • The content model is defined by a sequence group.
  • The sequence compositor occurs directly below a named complex-type element.
  • The children of the sequence group are (local) element declarations.
  • The names of the elements in the sequence are distinct. For now, additional restrictions are assumed, for mere simplicity:
  • The hosting complex type does not declare any attributes.
  • The elements in the sequence are required. Without loss of generality, we use a complex-type definition to host the content model. (That is, we could also use a root-element declaration.)

Schema sample (Flat sequences)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <!-- A very simple type of addresses -->
     <xs:complexType name="Address">
          <xs:sequence>
               <xs:element name="Name" type="xs:string"/>
               <xs:element name="Zip" type="xs:int"/>
               <xs:element name="Street" type="xs:string"/>
          </xs:sequence>
     </xs:complexType>
</xs:schema>

Flat sequences are mapped as follows:

  • (The hosting complex type is mapped to a class.)
  • The (local) element declarations are mapped to properties.
  • There are getters and setters for each property.
  • The precise mapping of element particles to properties is discussed elsewhere.

OO API

class Address : XTypedElement
{
   	constructor	  	Address();
   	explicit cast	  	Address(System.Xml.Linq.XElement xe);
   	property	  	string	  	Name	  	{ get; set; }
   	property	  	int	  	Zip	  	{ get; set; }
   	property	  	string	  	Street	  	{ get; set; }
}

Type and element references

Executive summary

  • There are OO counterparts for the built-in XSD simple types.
  • Element references are mapped to the class name for the referenced element.
  • Likewise for type references for complex types.
  • Derived simple types do not "nominally" participate in the mapping.
  • The name of a local element declaration defines the property name.
  • Element names and names of referenced types are subject to name mapping.

The following schema exercises type references for simple and complex types.

Schema sample (Type references)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <!-- A host for the references to follow -->
     <xs:complexType name="Customer">
          <xs:sequence>
               <xs:element name="Name" type="xs:string"/>
               <xs:element name="Age" type="AgeType"/>
               <xs:element name="Address" type="AddressType"/>
          </xs:sequence>
     </xs:complexType>
     <!-- A complex type to be referenced -->
     <xs:complexType name="AddressType">
          <xs:sequence>
               <xs:element name="Zip" type="xs:int"/>
               <xs:element name="Street" type="xs:string"/>
          </xs:sequence>
     </xs:complexType>
     <!-- A simple type to be referenced -->
     <xs:simpleType name="AgeType">
          <xs:restriction base="xs:int">
               <xs:minInclusive value="0"/>
               <xs:maxInclusive value="200"/>
          </xs:restriction>
     </xs:simpleType>
</xs:schema>

Simple-type references are mapped, by default, to references of the OO counterpart of the built-in XSD base type of the referenced type. The constraints for the simple type are enforced by the properties for the corresponding elements. Note: In the current release of LINQ to XSD, setters are validated, but not getters. This may be change. Complex-type references are always mapped to the class name for the complex type.

OO API (Type references)

class Customer : XTypedElement
{
   	constructor	  	Customer();
   	explicit cast	  	Customer(System.Xml.Linq.XElement xe);
   	property	  	string	  	Name	  	{ get; set; }
   	property	  	int	  	Age	  	{ get; set; }
   	property	  	AddressType	  	Address	  	{ get; set; }
}
class AddressType : XTypedElement
{
   	constructor	  	AddressType();
   	explicit cast	  	AddressType(System.Xml.Linq.XElement xe);
   	property	  	int	  	Zip	  	{ get; set; }
   	property	  	string	  	Street	  	{ get; set; }
}

The following schema varies the above schema such that:

  • It uses element declarations instead of type definitions;
  • It uses element references instead of local element declarations with type references.

Schema sample (Element references)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <!-- A host for the references to follow -->
     <xs:element name="Customer">
          <xs:complexType>
               <xs:sequence>
                    <xs:element name="Name" type="xs:string"/>
                    <xs:element ref="Age"/>
                    <xs:element ref="Address"/>
               </xs:sequence>
          </xs:complexType>
     </xs:element>
     <!-- A referable element of a complex type -->
     <xs:element name="Address">
          <xs:complexType>
               <xs:sequence>
                    <xs:element name="Zip" type="xs:int"/>
                    <xs:element name="Street" type="xs:string"/>
               </xs:sequence>
          </xs:complexType>
     </xs:element>
     <!-- A referable element of a simple type -->
     <xs:element name="Age">
          <xs:simpleType>
               <xs:restriction base="xs:int">
                    <xs:minInclusive value="0"/>
                    <xs:maxInclusive value="200"/>
               </xs:restriction>
          </xs:simpleType>
     </xs:element>
</xs:schema>

Element references are always mapped to "wrapper" references. This rule is applied regardless of whether the content model is or complex.

OO API (Element references)

class Customer : XTypedElement
{
   	constructor	  	Customer();
   	explicit cast	  	Customer(System.Xml.Linq.XElement xe);
   	property	  	string	  	Name	  	{ get; set; }
   	property	  	Age	  	Age	  	{ get; set; }
   	property	  	Address	  	Address	  	{ get; set; }
}
class Address : XTypedElement
{
   	constructor	  	Address();
   	explicit cast	  	Address(System.Xml.Linq.XElement xe);
   	property	  	int	  	Zip	  	{ get; set; }
   	property	  	string	  	Street	  	{ get; set; }
}
class Age : XTypedElement
{
   	constructor	  	Age();
   	explicit cast	  	Age(System.Xml.Linq.XElement xe);
   	property	  	int	  	TypedValue	  	{ get; set; }
}

Optional elements

An element is optional, if the (local) element declaration is attributed as follows:

  • There is an attribute minOccurs="0".
  • The value of the maxOccurs is 1 (which is the default). The mapping of optionality depends on the mapping of the involved content type:
  • If the element type is mapped to a CLR-value type, then optionality maps to nullable types.
  • Otherwise, optionality is not explicitly represented by the resulting CLR reference type.
  • Clearly, all complex-content types are mapped to CLR reference types.
  • Hence, optional and required elements of a complex content type are mapped in the same way.

Schema sample (Optional elements)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <!-- Customer information with optional age and shipping-address information -->
     <xs:complexType name="Customer">
          <xs:sequence>
               <xs:element name="Name" type="xs:string"/>
               <xs:element name="Age" type="xs:int" minOccurs="0"/>
               <xs:element name="BillAddress" type="Address"/>
               <xs:element name="ShipAddress" type="Address" minOccurs="0"/>
          </xs:sequence>
     </xs:complexType>
     <!-- Part 1 of street address is required; part 2 is optional -->
     <xs:complexType name="Address">
          <xs:sequence>
               <xs:element name="Zip" type="xs:int"/>
               <xs:element name="Street1" type="xs:string"/>
               <xs:element name="Street2" type="xs:string" minOccurs="0"/>
          </xs:sequence>
     </xs:complexType>
</xs:schema>

OO API (Use of nullable types)

class Customer : XTypedElement
{
   	constructor	  	Customer();
   	explicit cast	  	Customer(System.Xml.Linq.XElement xe);
   	property	  	string	  	Name	  	{ get; set; }
   	property	  	int?	  	Age	  	{ get; set; }
   	property	  	Address	  	BillAddress	  	{ get; set; }
   	property	  	Address	  	ShipAddress	  	{ get; set; }
}
class Address : XTypedElement
{
   	constructor	  	Address();
   	explicit cast	  	Address(System.Xml.Linq.XElement xe);
   	property	  	int	  	Zip	  	{ get; set; }
   	property	  	string	  	Street1	  	{ get; set; }
   	property	  	string	  	Street2	  	{ get; set; }
}

Given the missing disoverability of optionality for reference types, the classes generated by LINQ to XSD may document optionality as part of the tool tips for the relevant properties.

Repeating elements

An element is repeating, if the element declaration is attributed as follows:

  • The value of the maxOccurs attribute is different from 0 and 1 (default).
  • We say that the particle is a possibly empty list particle if minOccurs="0".
  • Otherwise, we say that the particle is a non-empty list particle.

The mapping of repeating elements is defined as follows:

  • Suppose t is result of mapping the element type of the particle.
  • Then, the property type for the mapped element particle is IList appled to t.
  • Hence, the observable CLR type does not resemble the precise occurrence constraints.

Schema sample (Repeating elements)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <!-- A figure is a potentially empty list of lines. -->
     <xs:element name="Figure">
          <xs:complexType>
               <xs:sequence>
                    <xs:element ref="Line" minOccurs="0" maxOccurs="unbounded"/>
               </xs:sequence>
          </xs:complexType>
     </xs:element>
     <!-- A line consists of 2 or more points. -->
     <xs:element name="Line">
          <xs:complexType>
               <xs:sequence>
                    <xs:element ref="Point" minOccurs="2" maxOccurs="unbounded"/>
               </xs:sequence>
          </xs:complexType>
     </xs:element>
     <xs:element name="Point">
          <xs:complexType>
               <xs:sequence>
                    <xs:element name="xCoord" type="xs:int"/>
                    <xs:element name="yCoord" type="xs:int"/>
               </xs:sequence>
          </xs:complexType>
     </xs:element>
</xs:schema>

OO API (Use of IList interface)

class Figure : XTypedElement
{
   	constructor	  	Figure();
   	explicit cast	  	Figure(System.Xml.Linq.XElement xe);
   	property	  	IList<Line>	  	Line	  	{ get; set; }
}
class Line : XTypedElement
{
   	constructor	  	Line();
   	explicit cast	  	Line(System.Xml.Linq.XElement xe);
   	property	  	IList<Point>	  	Point	  	{ get; set; }
}
class Point : XTypedElement
{
   	constructor	  	Point();
   	explicit cast	  	Point(System.Xml.Linq.XElement xe);
   	property	  	int	  	xCoord	  	{ get; set; }
   	property	  	int	  	yCoord	  	{ get; set; }
}

Given the missing disoverability of non-empty versus empty list status (or more specific bounds than 0, 1 and unbounded), the class that are generated by LINQ to XSD may document the status as part of the tool tips for the relevant properties.

Attributes

Attribute declarations are mapped to properties that are added to the class that hosts the complex type of which the attributes are part of. (For simplicity, it is assumed that element and attribute names are distinct in a given scope. Otherwise, special rules of name mapping apply.)

Schema sample (A complex type with an attribute declaration)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <xs:complexType name="Product">
          <xs:sequence>
               <xs:element name="Number" type="xs:integer"/>
               <xs:element name="Name" type="xs:string"/>
          </xs:sequence>
          <xs:attribute name="EffDate" type="xs:date" use="optional"/>
     </xs:complexType>
</xs:schema>

OO API

class Product : XTypedElement
{
   	constructor	  	Product();
   	explicit cast	  	Product(System.Xml.Linq.XElement xe);
   	property	  	decimal	  	Number	  	{ get; set; }
   	property	  	string	  	Name	  	{ get; set; }
   	property	  	System.DateTime?	  	EffDate	  	{ get; set; }
}

OO API (Properties for attributes)

class Product : XTypedElement
{
   	constructor	  	Product();
   	explicit cast	  	Product(System.Xml.Linq.XElement xe);
   	property	  	decimal	  	Number	  	{ get; set; }
   	property	  	string	  	Name	  	{ get; set; }
   	property	  	System.DateTime?	  	EffDate	  	{ get; set; }
}

All attribute declarations can be thought as element particles in a sequence. Hence, the following schema maps to the same object model as the earlier schema. Schema sample (Elements in place of attributes)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <xs:complexType name="Product">
          <xs:sequence>
               <xs:element name="Number" type="xs:integer"/>
               <xs:element name="Name" type="xs:string"/>
               <xs:element name="EffDate" type="xs:date" minOccurs="0"/>
          </xs:sequence>
     </xs:complexType>
</xs:schema>

Flat choices

Characteristics of flat choices:

  • The content model is defined by a choice group.
  • The compositor occurs directly below a complex-type element.
  • The children of the choice group are (local) element declarations.
  • The element names are distinct (required per XSD validity).
  • The element types are described by type references.

Schema sample (Flat choice)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <xs:element name="BillTo">
          <!-- Both street and pobox are of type xs:string. -->
          <xs:complexType>
               <xs:choice>
                    <xs:element name="Street" type="xs:string"/>
                    <xs:element name="Pobox" type="xs:string"/>
               </xs:choice>
          </xs:complexType>
     </xs:element>
</xs:schema>

The choice group is essentially mapped as the same sequence group except that:

  • The particles are mapped to properties as if they were optional particles.
  • Each of the resulting setters unsets all the other setters.

OO API (Flat choices on element particles)

class BillTo : XTypedElement
{
   	constructor	  	BillTo();
   	explicit cast	  	BillTo(System.Xml.Linq.XElement xe);
   	property	  	string	  	Street	  	{ get; set; }
   	property	  	string	  	Pobox	  	{ get; set; }
}

Programmatic case discrimination choices can be based on non-null tests per branch that are appropriate casceded in conditionals. For a more restricted form of choices, convenience for construction can be provided. That is, when the choice at hand uses plain element particles with distinct element types that are also mapped to different OO types, then we can use the (mapped) types themselves to provide an overloaded constructor.

Schema sample (A choice with distinct element types for the branches)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <!-- Arithmetic expression forms combined by choice -->
     <xs:complexType name="Exp">
          <xs:choice>
               <xs:element name="Const" type="xs:int"/>
               <xs:element name="Add" type="Add"/>
          </xs:choice>
     </xs:complexType>
     <!-- Addition as an expression form -->
     <xs:complexType name="Add">
          <xs:sequence>
               <xs:element name="Left" type="Exp"/>
               <xs:element name="Right" type="Exp"/>
          </xs:sequence>
     </xs:complexType>
</xs:schema>

Note that there are two constructors, corresponding to a binary choice.

OO API

class Exp : XTypedElement
{
   	constructor	  	Exp();
   	constructor	  	Exp(int? Const);
   	constructor	  	Exp(Add Add);
   	explicit cast	  	Exp(System.Xml.Linq.XElement xe);
   	property	  	int?	  	Const	  	{ get; set; }
   	property	  	Add	  	Add	  	{ get; set; }
}
class Add : XTypedElement
{
   	constructor	  	Add();
   	explicit cast	  	Add(System.Xml.Linq.XElement xe);
   	property	  	Exp	  	Left	  	{ get; set; }
   	property	  	Exp	  	Right	  	{ get; set; }
}

The described mapping rules do not readily enable the discoverability of mutually exclusive properties (in the sense of choice), when compared to the combined use of properties (in the sense of sequence). The classes generated by LINQ to XSD may document the content model as part of the tool tips for the relevant properties.

Recurrent element names

An element name is said to be recurrent in a given content model, if the content model comprises multiple element declarations of the given name. Recurrence is mapped such that all the relevant element declarations are mapped to a single property with a type as in the case of a repeating element particle. That is, there is no 1:1 correspondence of element particles and properties; instead there is 1:1 correspondence of element names and properties.

Schema sample (Recurrent element names)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <!-- A figure as a list of lines -->
     <xs:element name="Figure">
          <xs:complexType>
               <xs:sequence>
                    <xs:element ref="Line" minOccurs="0" maxOccurs="unbounded"/>
               </xs:sequence>
          </xs:complexType>
     </xs:element>
     <!-- A line that consist of two points. -->
     <xs:element name="Line">
          <xs:complexType>
               <xs:sequence>
                    <xs:element ref="Point"/>
                    <xs:element ref="Point"/>
               </xs:sequence>
          </xs:complexType>
     </xs:element>
     <xs:element name="Point">
          <xs:complexType>
               <xs:sequence>
                    <xs:element name="xCoord" type="xs:int"/>
                    <xs:element name="yCoord" type="xs:int"/>
               </xs:sequence>
          </xs:complexType>
     </xs:element>
</xs:schema>

OO API

class Figure : XTypedElement
{
   	constructor	  	Figure();
   	explicit cast	  	Figure(System.Xml.Linq.XElement xe);
   	property	  	IList<Line>	  	Line	  	{ get; set; }
}
class Line : XTypedElement
{
   	constructor	  	Line();
   	explicit cast	  	Line(System.Xml.Linq.XElement xe);
   	property	  	IList<Point>	  	Point	  	{ get; set; }
}
class Point : XTypedElement
{
   	constructor	  	Point();
   	explicit cast	  	Point(System.Xml.Linq.XElement xe);
   	property	  	int	  	xCoord	  	{ get; set; }
   	property	  	int	  	yCoord	  	{ get; set; }
}

Nested content models

Schema sample (Nested, repeating sequences)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <xs:complexType name="JobOffer">
          <xs:sequence>
               <xs:element name="JobId" type="xs:string"/>
               <xs:sequence minOccurs="0" maxOccurs="unbounded">
                    <xs:element name="Name" type="xs:string"/>
                    <xs:element name="SSN" type="xs:int"/>
               </xs:sequence>
          </xs:sequence>
     </xs:complexType>
</xs:schema>

The LINQ to XSD mapping is instance-oriented. That is, the nesting of compositors is not represented by the API of the classes generated by LINQ to XSD. Instead, all element names in a content model give rise to properties. We refer to the discussion of "append semantics" in the overview and the manual for LINQ to XSD.

OO API

class JobOffer : XTypedElement
{
   	constructor	  	JobOffer();
   	explicit cast	  	JobOffer(System.Xml.Linq.XElement xe);
   	property	  	string	  	JobId	  	{ get; set; }
   	property	  	IList<string>	  	Name	  	{ get; set; }
   	property	  	IList<int>	  	SSN	  	{ get; set; }
}

Anonymous types

The mapping for root elements with anonymous types was defined elsewhere. The mapping for local elements with anonymous simple types is trivial because the (derived) simple type or the type union or list type is reduced to the base built-in type as far as the API type is concerned. The case of local elements with anonymous complex types remains.

Schema sample (A schema with nested, anonymous, complex types)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <xs:element name="Bib">
          <xs:complexType>
               <xs:sequence>
                    <xs:element maxOccurs="unbounded" name="Book">
                         <xs:complexType>
                              <xs:sequence>
                                   <xs:choice maxOccurs="unbounded">
                                        <xs:element name="Title" type="xs:string"/>
                                        <xs:element maxOccurs="unbounded" name="Author">
                                             <xs:complexType>
                                                  <xs:sequence>
                                                       <xs:element name="Last" type="xs:string"/>
                                                       <xs:element name="First" type="xs:string"/>
                                                  </xs:sequence>
                                             </xs:complexType>
                                        </xs:element>
                                        <xs:element name="Editor">
                                             <xs:complexType>
                                                  <xs:sequence>
                                                       <xs:element name="Last" type="xs:string"/>
                                                       <xs:element name="First" type="xs:string"/>
                                                       <xs:element name="Affiliation">
                                                            <xs:complexType>
                                                                 <xs:simpleContent>
                                                                      <xs:extension base="xs:string">
                                                                           <xs:attribute name="Type" type="xs:string" use="required"/>
                                                                      </xs:extension>
                                                                 </xs:simpleContent>
                                                            </xs:complexType>
                                                       </xs:element>
                                                  </xs:sequence>
                                             </xs:complexType>
                                        </xs:element>
                                        <xs:element name="Publisher" type="xs:string"/>
                                        <xs:element name="Price" type="xs:decimal"/>
                                   </xs:choice>
                              </xs:sequence>
                              <xs:attribute name="Year" type="xs:unsignedShort" use="required"/>
                              <xs:attribute name="Anson" type="xs:boolean" use="optional"/>
                              <xs:attribute name="Joe" type="xs:string" use="optional"/>
                         </xs:complexType>
                    </xs:element>
               </xs:sequence>
          </xs:complexType>
     </xs:element>
</xs:schema>

By default, such nesting of elements and types is mapped to nesting of OO classes.

OO API (Default mapping)

class Bib : XTypedElement
{
   	constructor	  	Bib();
   	explicit cast	  	Bib(System.Xml.Linq.XElement xe);
   	
class BookLocalType : XTypedElement
{
   	constructor	  	BookLocalType();
   	explicit cast	  	BookLocalType(System.Xml.Linq.XElement xe);
   	
class AuthorLocalType : XTypedElement
{
   	constructor	  	AuthorLocalType();
   	explicit cast	  	AuthorLocalType(System.Xml.Linq.XElement xe);
   	property	  	string	  	Last	  	{ get; set; }
   	property	  	string	  	First	  	{ get; set; }
}
   	
class EditorLocalType : XTypedElement
{
   	constructor	  	EditorLocalType();
   	explicit cast	  	EditorLocalType(System.Xml.Linq.XElement xe);
   	
class AffiliationLocalType : XTypedElement
{
   	constructor	  	AffiliationLocalType();
   	explicit cast	  	AffiliationLocalType(System.Xml.Linq.XElement xe);
   	property	  	string	  	TypedValue	  	{ get; set; }
   	property	  	string	  	Type	  	{ get; set; }
}
   	property	  	string	  	Last	  	{ get; set; }
   	property	  	string	  	First	  	{ get; set; }
   	property	  	AffiliationLocalType	  	Affiliation	  	{ get; set; }
}
   	property	  	IList<string>	  	Title	  	{ get; set; }
   	property	  	IList<AuthorLocalType>	  	Author	  	{ get; set; }
   	property	  	IList<EditorLocalType>	  	Editor	  	{ get; set; }
   	property	  	IList<string>	  	Publisher	  	{ get; set; }
   	property	  	IList<decimal>	  	Price	  	{ get; set; }
   	property	  	ushort	  	Year	  	{ get; set; }
   	property	  	bool?	  	Anson	  	{ get; set; }
   	property	  	string	  	Joe	  	{ get; set; }
}
   	property	  	IList<BookLocalType>	  	Book	  	{ get; set; }
}

However, one can also request a transformation for de-anonymization. The topic of schema normalization is discussed in the LINQ to XSD manual. De-anonymization modifies the mapping such that anonymous complex types are defined globally, while the local element names are leveraged as type names, when this is possible without introducing type clashes. Accordingly, the resulting object model does not comprise any nested classes.

OO API (Mapping with de-anonymization)

class Bib : XTypedElement
{
   	constructor	  	Bib();
   	explicit cast	  	Bib(System.Xml.Linq.XElement xe);
   	property	  	IList<Book>	  	Book	  	{ get; set; }
}
class Book : XTypedElement
{
   	constructor	  	Book();
   	explicit cast	  	Book(System.Xml.Linq.XElement xe);
   	property	  	IList<string>	  	Title	  	{ get; set; }
   	property	  	IList<author>	  	author	  	{ get; set; }
   	property	  	IList<Editor>	  	Editor	  	{ get; set; }
   	property	  	IList<string>	  	Publisher	  	{ get; set; }
   	property	  	IList<decimal>	  	Price	  	{ get; set; }
   	property	  	ushort	  	Year	  	{ get; set; }
   	property	  	bool?	  	Anson	  	{ get; set; }
   	property	  	string	  	Joe	  	{ get; set; }
}
class author : XTypedElement
{
   	constructor	  	author();
   	explicit cast	  	author(System.Xml.Linq.XElement xe);
   	property	  	string	  	Last	  	{ get; set; }
   	property	  	string	  	First	  	{ get; set; }
}
class Editor : XTypedElement
{
   	constructor	  	Editor();
   	explicit cast	  	Editor(System.Xml.Linq.XElement xe);
   	property	  	string	  	Last	  	{ get; set; }
   	property	  	string	  	First	  	{ get; set; }
   	property	  	Affiliation	  	Affiliation	  	{ get; set; }
}
class Affiliation : XTypedElement
{
   	constructor	  	Affiliation();
   	explicit cast	  	Affiliation(System.Xml.Linq.XElement xe);
   	property	  	string	  	TypedValue	  	{ get; set; }
   	property	  	string	  	Type	  	{ get; set; }
}

Fixed and default values

LinqToXsd only provides support for default values. Fixed values are not yet currently supported.

Wildcards

Schema sample (A schema with wildcards)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <xs:complexType name="ProductType">
          <xs:sequence>
               <xs:element name="Number" type="xs:string"/>
               <xs:element name="Name" type="xs:string"/>
               <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
          </xs:sequence>
          <xs:anyAttribute namespace="##other" processContents="skip"/>
     </xs:complexType>
</xs:schema>

Element wildcards are mapped to a designated API member.

Note: Attribute wildcards are ignored by the mapping in the current release of LINQ to XSD and hence require the untyped API.

OO API (Designated members for wildcards)

class ProductType : XTypedElement
{
   	constructor	  	ProductType();
   	explicit cast	  	ProductType(System.Xml.Linq.XElement xe);
   	property	  	string	  	Number	  	{ get; set; }
   	property	  	string	  	Name	  	{ get; set; }
   	property	  	IEnumerable<System.Xml.Linq.XElement>	  	Any	  	{ get;  }
}

The Any property is always of type XElement or a list type thereof. Occurrence constraints and recurrence of Any are subject to the same rules as for normal element particles. That is, if the Any is neither repeating nor recurring, then the generated property is of type XElement. Otherwise, the property is of the list type.

Substitution forms

Subsections

Complex-type extension

For simplicity, the following assumptions are made:

  • A complex base type is extended by complex content.
  • Substitutability is unrestricted, i.e., block and final are not used.
  • The derived content model is a sequence on element particles.
  • The derived type is non-anonymous.

Schema sample

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <!-- A base type of products -->
     <xs:complexType name="Product">
          <xs:sequence>
               <xs:element name="Number" type="xs:integer"/>
               <xs:element name="Name" type="xs:string"/>
          </xs:sequence>
     </xs:complexType>
     <!-- shirt extends product -->
     <xs:complexType name="Shirt">
          <xs:complexContent>
               <xs:extension base="Product">
                    <xs:sequence>
                         <xs:element name="Size" type="xs:string"/>
                         <xs:element name="Color" type="xs:string"/>
                    </xs:sequence>
               </xs:extension>
          </xs:complexContent>
     </xs:complexType>
     <!-- hat extends product -->
     <xs:complexType name="Hat">
          <xs:complexContent>
               <xs:extension base="Product">
                    <xs:sequence>
                         <xs:element name="Size" type="xs:int"/>
                    </xs:sequence>
               </xs:extension>
          </xs:complexContent>
     </xs:complexType>
</xs:schema>

Such type derivation by extension is mapped as follows:

  • Both base type and derived type are mapped to classes.
  • The derivation relationship is mapped to OO class inheritance.
  • That is, the "derived" class inherits from the "base" class.
  • Roots in the derivation hierarchy inherit from "XTypedElement" as usual.
  • The properties for the added particles appear in the derived class.

OO API

class Product : XTypedElement
{
   	constructor	  	Product();
   	explicit cast	  	Product(System.Xml.Linq.XElement xe);
   	property	  	decimal	  	Number	  	{ get; set; }
   	property	  	string	  	Name	  	{ get; set; }
}
class Shirt : Product
{
   	constructor	  	Shirt();
   	explicit cast	  	Shirt(System.Xml.Linq.XElement xe);
   	property	  	string	  	Size	  	{ get; set; }
   	property	  	string	  	Color	  	{ get; set; }
}
class Hat : Product
{
   	constructor	  	Hat();
   	explicit cast	  	Hat(System.Xml.Linq.XElement xe);
   	property	  	int	  	Size	  	{ get; set; }
}

Extension of simple content

Note: This topic is not documented in the current release of LINQ to XSD.

Simple-type restriction

Note: This topic is not documented in the current release of LINQ to XSD.

Complex-type restriction

Schema sample

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <!-- A base type of products -->
     <xs:complexType name="Product">
          <xs:sequence>
               <xs:element name="Number" type="xs:integer"/>
               <xs:element name="Name" type="xs:string"/>
               <xs:element name="Size" type="xs:int" minOccurs="0"/>
               <xs:element name="Color" type="xs:string" minOccurs="0"/>
          </xs:sequence>
     </xs:complexType>
     <!-- A restriction of product -->
     <xs:complexType name="RigidProduct">
          <xs:complexContent>
               <xs:restriction base="Product">
                    <xs:sequence>
                         <xs:element name="Number" type="xs:integer"/>
                         <xs:element name="Name" type="xs:string"/>
                         <xs:element name="Size" type="xs:int"/>
                    </xs:sequence>
               </xs:restriction>
          </xs:complexContent>
     </xs:complexType>
</xs:schema>

The derived type is mapped to a subclass of the class for the base type.

Note: In the current release of LINQ to XSD, the restrictions are not checked in any way.

OO API

class Product : XTypedElement
{
   	constructor	  	Product();
   	explicit cast	  	Product(System.Xml.Linq.XElement xe);
   	property	  	decimal	  	Number	  	{ get; set; }
   	property	  	string	  	Name	  	{ get; set; }
   	property	  	int?	  	Size	  	{ get; set; }
   	property	  	string	  	Color	  	{ get; set; }
}
class RigidProduct : Product
{
   	constructor	  	RigidProduct();
   	explicit cast	  	RigidProduct(System.Xml.Linq.XElement xe);
}

Susbstitution groups

Here is an example for using substitution groups. (We continue the example on type derivation by extension for complex types.)

Schema sample (Substitution groups)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <xs:element name="Product" type="ProductType"/>
     <xs:element name="Shirt" type="ShirtType"/>
     <xs:element name="Hat" type="HatType"/>
     <xs:complexType name="ProductType">
          <xs:sequence>
               <!-- product details omitted -->
          </xs:sequence>
     </xs:complexType>
     <xs:complexType name="ShirtType">
          <xs:complexContent>
               <xs:extension base="ProductType">
                    <xs:sequence>
                         <!-- shirt details omitted -->
                    </xs:sequence>
               </xs:extension>
          </xs:complexContent>
     </xs:complexType>
     <xs:complexType name="HatType">
          <xs:complexContent>
               <xs:extension base="ProductType">
                    <xs:sequence>
                         <!-- hat details omitted -->
                    </xs:sequence>
               </xs:extension>
          </xs:complexContent>
     </xs:complexType>
</xs:schema>

Substitution groups are mapped in accordance to the combined use of element declarations and complex-type definitions. In addition, the following mapping rules apply:

  • The type derivation hierarchy is mapped as in the case of plain type derivation.
  • The global element declarations are mapped as usual except for the superclass constraint.
  • Classes for substitution group members inherit from the class for the head.

OO API

class ProductType : XTypedElement
{
   	constructor	  	ProductType();
   	explicit cast	  	ProductType(System.Xml.Linq.XElement xe);
}
class ShirtType : ProductType
{
   	constructor	  	ShirtType();
   	explicit cast	  	ShirtType(System.Xml.Linq.XElement xe);
}
class HatType : ProductType
{
   	constructor	  	HatType();
   	explicit cast	  	HatType(System.Xml.Linq.XElement xe);
}
class Product : XTypedElement
{
   	constructor	  	Product();
   	constructor	  	Product(ProductType content);
   	explicit cast	  	Product(System.Xml.Linq.XElement xe);
   	property	  	ProductType	  	Content	  	{ get;  }
}
class Shirt : XTypedElement
{
   	constructor	  	Shirt();
   	constructor	  	Shirt(ShirtType content);
   	explicit cast	  	Shirt(System.Xml.Linq.XElement xe);
   	property	  	ShirtType	  	Content	  	{ get;  }
}
class Hat : XTypedElement
{
   	constructor	  	Hat();
   	constructor	  	Hat(HatType content);
   	explicit cast	  	Hat(System.Xml.Linq.XElement xe);
   	property	  	HatType	  	Content	  	{ get;  }
}

Control of substitutability

Note: This topic is not documented in the current release of LINQ to XSD.

Trivially mapped XSD constructs

Subsections

Group definitions

These definitions are not mapped. References to these definitions are mapped by inlining them in the place of the reference. Note: This approach may be refined in a future version of LINQ to XSD so that groups are mapped for better code factorization.

Global attribute declarations

These declarations are not mapped. References to these declarations are mapped by inlining them in the place of the reference.

Global attribute-group definitions

These definitions are not mapped. References to these definitions are mapped by inlining them in the place of the reference.

Redefinitions

The System.Xml.Schema semantics of redefinitions applies. Essentially, this implies that redefinitions override the original definitions.

Identity constraints

Identity constraints are not taken into account, in any way. Normal validation is supposed to check these constraints.

Mixed content

There are no designated API members for mixed content. Interim text is discoverable and definable through the XElement interface. Tool tips may document the mixed-content status of a class.

Appendix: Mapping of built-in simple types

By default, each and every XSD built-in simple type is mapped to a CLR type, mostly to a CLR value type or to string. This default mapping is exercised below by means of a content model with an element particle for each and every built-in type.

Schema sample (All of XSD's built-in simple types)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <!-- An illustrative type that exercises all built-in simple types. -->
     <!-- Indeed, all these types are listed in alphabetic order. -->
     <xs:complexType name="simpleType">
          <xs:sequence>
               <xs:element name="xsAnySimpleType" type="xs:anySimpleType"/>
               <xs:element name="xsAnyURI" type="xs:anyURI"/>
               <xs:element name="xsBase64Binary" type="xs:base64Binary"/>
               <xs:element name="xsBoolean" type="xs:boolean"/>
               <xs:element name="xsByte" type="xs:byte"/>
               <xs:element name="xsDate" type="xs:date"/>
               <xs:element name="xsDateTime" type="xs:dateTime"/>
               <xs:element name="xsENTITIES" type="xs:ENTITIES"/>
               <xs:element name="xsENTITY" type="xs:ENTITY"/>
               <xs:element name="xsFloat" type="xs:float"/>
               <xs:element name="xsDecimal" type="xs:decimal"/>
               <xs:element name="xsDouble" type="xs:double"/>
               <xs:element name="xsDuration" type="xs:duration"/>
               <xs:element name="xsGDay" type="xs:gDay"/>
               <xs:element name="xsGMonth" type="xs:gMonth"/>
               <xs:element name="xsGMonthDay" type="xs:gMonthDay"/>
               <xs:element name="xsGYear" type="xs:gYear"/>
               <xs:element name="xsGYearMonth" type="xs:gYearMonth"/>
               <xs:element name="xsHexBinary" type="xs:hexBinary"/>
               <xs:element name="xsID" type="xs:ID"/>
               <xs:element name="xsIDREF" type="xs:IDREF"/>
               <xs:element name="xsIDREFS" type="xs:IDREFS"/>
               <xs:element name="xsInt" type="xs:int"/>
               <xs:element name="xsInteger" type="xs:integer"/>
               <xs:element name="xsLanguage" type="xs:language"/>
               <xs:element name="xsLong" type="xs:long"/>
               <xs:element name="xsName" type="xs:Name"/>
               <xs:element name="xsNCName" type="xs:NCName"/>
               <xs:element name="xsNegativeInteger" type="xs:negativeInteger"/>
               <xs:element name="xsNMTOKEN" type="xs:NMTOKEN"/>
               <xs:element name="xsNMTOKENS" type="xs:NMTOKENS"/>
               <xs:element name="xsNonNegativeInteger" type="xs:nonNegativeInteger"/>
               <xs:element name="xsNonPositiveInteger" type="xs:nonPositiveInteger"/>
               <xs:element name="xsNormalizedString" type="xs:normalizedString"/>
               <!-- xs:NOTATION was omitted since it is only used in derivations. -->
               <xs:element name="xsPositiveInteger" type="xs:positiveInteger"/>
               <xs:element name="xsQName" type="xs:QName"/>
               <xs:element name="xsUnsignedByte" type="xs:unsignedByte"/>
               <xs:element name="xsUnsignedInt" type="xs:unsignedInt"/>
               <xs:element name="xsUnsignedLong" type="xs:unsignedLong"/>
               <xs:element name="xsUnsignedShort" type="xs:unsignedShort"/>
               <xs:element name="xsShort" type="xs:short"/>
               <xs:element name="xsString" type="xs:string"/>
               <xs:element name="xsTime" type="xs:time"/>
               <xs:element name="xsToken" type="xs:token"/>
          </xs:sequence>
     </xs:complexType>
</xs:schema>

OO API (CLR counteparts for XSD built-in simple types)

class simpleType : XTypedElement
{
   	constructor	  	simpleType();
   	explicit cast	  	simpleType(System.Xml.Linq.XElement xe);
   	property	  	string	  	xsAnySimpleType	  	{ get; set; }
   	property	  	System.Uri	  	xsAnyURI	  	{ get; set; }
   	property	  	System.Byte[]	  	xsBase64Binary	  	{ get; set; }
   	property	  	bool	  	xsBoolean	  	{ get; set; }
   	property	  	sbyte	  	xsByte	  	{ get; set; }
   	property	  	System.DateTime	  	xsDate	  	{ get; set; }
   	property	  	System.DateTime	  	xsDateTime	  	{ get; set; }
   	property	  	IList<string>	  	xsENTITIES	  	{ get; set; }
   	property	  	string	  	xsENTITY	  	{ get; set; }
   	property	  	float	  	xsFloat	  	{ get; set; }
   	property	  	decimal	  	xsDecimal	  	{ get; set; }
   	property	  	double	  	xsDouble	  	{ get; set; }
   	property	  	System.TimeSpan	  	xsDuration	  	{ get; set; }
   	property	  	System.DateTime	  	xsGDay	  	{ get; set; }
   	property	  	System.DateTime	  	xsGMonth	  	{ get; set; }
   	property	  	System.DateTime	  	xsGMonthDay	  	{ get; set; }
   	property	  	System.DateTime	  	xsGYear	  	{ get; set; }
   	property	  	System.DateTime	  	xsGYearMonth	  	{ get; set; }
   	property	  	System.Byte[]	  	xsHexBinary	  	{ get; set; }
   	property	  	string	  	xsID	  	{ get; set; }
   	property	  	string	  	xsIDREF	  	{ get; set; }
   	property	  	IList<string>	  	xsIDREFS	  	{ get; set; }
   	property	  	int	  	xsInt	  	{ get; set; }
   	property	  	decimal	  	xsInteger	  	{ get; set; }
   	property	  	string	  	xsLanguage	  	{ get; set; }
   	property	  	long	  	xsLong	  	{ get; set; }
   	property	  	string	  	xsName	  	{ get; set; }
   	property	  	string	  	xsNCName	  	{ get; set; }
   	property	  	decimal	  	xsNegativeInteger	  	{ get; set; }
   	property	  	string	  	xsNMTOKEN	  	{ get; set; }
   	property	  	IList<string>	  	xsNMTOKENS	  	{ get; set; }
   	property	  	decimal	  	xsNonNegativeInteger	  	{ get; set; }
   	property	  	decimal	  	xsNonPositiveInteger	  	{ get; set; }
   	property	  	string	  	xsNormalizedString	  	{ get; set; }
   	property	  	decimal	  	xsPositiveInteger	  	{ get; set; }
   	property	  	System.Xml.XmlQualifiedName	  	xsQName	  	{ get; set; }
   	property	  	byte	  	xsUnsignedByte	  	{ get; set; }
   	property	  	uint	  	xsUnsignedInt	  	{ get; set; }
   	property	  	ulong	  	xsUnsignedLong	  	{ get; set; }
   	property	  	ushort	  	xsUnsignedShort	  	{ get; set; }
   	property	  	short	  	xsShort	  	{ get; set; }
   	property	  	string	  	xsString	  	{ get; set; }
   	property	  	System.DateTime	  	xsTime	  	{ get; set; }
   	property	  	string	  	xsToken	  	{ get; set; }
}

Appendix: Name mapping

Note: This topic is not documented in the current release of LINQ to XSD.

Appendix: Namespace mapping

Note: This topic is not documented in the current release of LINQ to XSD.

Appendix: More samples

Subsections

Purchase orders

The following schema is used in the LINQ to XSD overview.

Schema sample

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <xs:element name="Batch">
          <xs:complexType>
               <xs:sequence>
                    <xs:element ref="PurchaseOrder" minOccurs="0" maxOccurs="unbounded"/>
               </xs:sequence>
          </xs:complexType>
     </xs:element>
     <xs:element name="PurchaseOrder">
          <xs:complexType>
               <xs:sequence>
                    <xs:element name="CustId" type="xs:string"/>
                    <xs:element ref="Item" minOccurs="0" maxOccurs="unbounded"/>
               </xs:sequence>
          </xs:complexType>
     </xs:element>
     <xs:element name="Item">
          <xs:complexType>
               <xs:sequence>
                    <xs:element name="ProdId" type="xs:string"/>
                    <xs:element name="Price" type="xs:double"/>
                    <xs:element name="Quantity" type="xs:int"/>
               </xs:sequence>
          </xs:complexType>
     </xs:element>
</xs:schema>

OO API

class Batch : XTypedElement
{
   	constructor	  	Batch();
   	explicit cast	  	Batch(System.Xml.Linq.XElement xe);
   	property	  	IList<PurchaseOrder>	  	PurchaseOrder	  	{ get; set; }
}
class PurchaseOrder : XTypedElement
{
   	constructor	  	PurchaseOrder();
   	explicit cast	  	PurchaseOrder(System.Xml.Linq.XElement xe);
   	property	  	string	  	CustId	  	{ get; set; }
   	property	  	IList<Item>	  	Item	  	{ get; set; }
}
class Item : XTypedElement
{
   	constructor	  	Item();
   	explicit cast	  	Item(System.Xml.Linq.XElement xe);
   	property	  	string	  	ProdId	  	{ get; set; }
   	property	  	double	  	Price	  	{ get; set; }
   	property	  	int	  	Quantity	  	{ get; set; }
}

Invoices for orders

The following schema is used in the XML 2006 paper.

Schema sample

<xs:schema xmlns:xmlns="http://www.w3.org/2001/XMLSchema">
     <xs:element name="Invoice">
          <xs:complexType>
               <xs:sequence>
                    <xs:element name="Name" type="string"/>
                    <xs:element name="Street" type="string"/>
                    <xs:element name="City" type="string"/>
                    <xs:element name="Zip" type="string"/>
                    <xs:element name="State" type="string"/>
                    <xs:element name="Position" maxOccurs="unbounded">
                         <xs:complexType>
                              <xs:sequence>
                                   <xs:element name="ProdId" type="string"/>
                                   <xs:element name="Price" type="double"/>
                                   <xs:element name="Quantity" type="int"/>
                              </xs:sequence>
                         </xs:complexType>
                    </xs:element>
                    <xs:element name="Total" type="double"/>
               </xs:sequence>
          </xs:complexType>
     </xs:element>
</xs:schema>

OO API

class Invoice : XTypedElement
{
   	constructor	  	Invoice();
   	explicit cast	  	Invoice(System.Xml.Linq.XElement xe);
   	property	  	string	  	Name	  	{ get; set; }
   	property	  	string	  	Street	  	{ get; set; }
   	property	  	string	  	City	  	{ get; set; }
   	property	  	string	  	Zip	  	{ get; set; }
   	property	  	string	  	State	  	{ get; set; }
   	property	  	IList<Position>	  	Position	  	{ get; set; }
   	property	  	double	  	Total	  	{ get; set; }
}
class Position : XTypedElement
{
   	constructor	  	Position();
   	explicit cast	  	Position(System.Xml.Linq.XElement xe);
   	property	  	string	  	ProdId	  	{ get; set; }
   	property	  	double	  	Price	  	{ get; set; }
   	property	  	int	  	Quantity	  	{ get; set; }
}

Company organization

The following schema is used in the LINQ to XSD demo.

Schema sample

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <xs:element name="Company">
          <xs:complexType>
               <xs:sequence>
                    <xs:element ref="Department" minOccurs="0" maxOccurs="unbounded"/>
               </xs:sequence>
          </xs:complexType>
     </xs:element>
     <xs:element name="Department">
          <xs:complexType>
               <xs:sequence>
                    <xs:element name="Label" type="xs:string"/>
                    <xs:element name="Manager" type="EmployeeType" minOccurs="0"/>
                    <xs:element ref="Member" minOccurs="0" maxOccurs="unbounded"/>
               </xs:sequence>
               <xs:attribute name="Deptno" type="xs:int"/>
          </xs:complexType>
     </xs:element>
     <xs:element name="Member">
          <xs:complexType>
               <xs:choice>
                    <xs:element name="Employee" type="EmployeeType"/>
                    <xs:element ref="Department"/>
               </xs:choice>
          </xs:complexType>
     </xs:element>
     <xs:complexType name="EmployeeType">
          <xs:sequence>
               <xs:element name="Name" type="xs:string"/>
               <xs:element name="Salary" type="xs:double"/>
          </xs:sequence>
     </xs:complexType>
</xs:schema>

OO API

class Company : XTypedElement
{
   	constructor	  	Company();
   	explicit cast	  	Company(System.Xml.Linq.XElement xe);
   	property	  	IList<Department>	  	Department	  	{ get; set; }
}
class Department : XTypedElement
{
   	constructor	  	Department();
   	explicit cast	  	Department(System.Xml.Linq.XElement xe);
   	property	  	string	  	Label	  	{ get; set; }
   	property	  	EmployeeType	  	Manager	  	{ get; set; }
   	property	  	IList<Member>	  	Member	  	{ get; set; }
   	property	  	int?	  	Deptno	  	{ get; set; }
}
class Member : XTypedElement
{
   	constructor	  	Member();
   	constructor	  	Member(EmployeeType Employee);
   	constructor	  	Member(Department Department);
   	explicit cast	  	Member(System.Xml.Linq.XElement xe);
   	property	  	EmployeeType	  	Employee	  	{ get; set; }
   	property	  	Department	  	Department	  	{ get; set; }
}
class EmployeeType : XTypedElement
{
   	constructor	  	EmployeeType();
   	explicit cast	  	EmployeeType(System.Xml.Linq.XElement xe);
   	property	  	string	  	Name	  	{ get; set; }
   	property	  	double	  	Salary	  	{ get; set; }
}

Language syntax

The following schema is used in the LINQ to XSD demo.

Schema sample

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <xs:element name="Program" type="Block"/>
     <xs:complexType name="Expr" abstract="true"/>
     <xs:complexType name="Constant">
          <xs:complexContent>
               <xs:extension base="Expr">
                    <xs:choice>
                         <xs:element name="Integer" type="xs:int"/>
                         <xs:element name="Boolean" type="xs:boolean"/>
                    </xs:choice>
               </xs:extension>
          </xs:complexContent>
     </xs:complexType>
     <xs:complexType name="Variable">
          <xs:complexContent>
               <xs:extension base="Expr">
                    <xs:sequence>
                         <xs:element name="Id" type="xs:string"/>
                    </xs:sequence>
               </xs:extension>
          </xs:complexContent>
     </xs:complexType>
     <xs:complexType name="Block">
          <xs:complexContent>
               <xs:extension base="Expr">
                    <xs:sequence>
                         <xs:element name="Decl" type="Decl" minOccurs="0" maxOccurs="unbounded"/>
                         <xs:element name="Expr" type="Expr" maxOccurs="unbounded"/>
                    </xs:sequence>
               </xs:extension>
          </xs:complexContent>
     </xs:complexType>
     <xs:complexType name="Decl">
          <xs:sequence>
               <xs:element name="Id" type="xs:string"/>
               <xs:element name="Type" type="Type"/>
          </xs:sequence>
     </xs:complexType>
     <xs:complexType name="Type" abstract="true"/>
     <xs:complexType name="Integer">
          <xs:complexContent>
               <xs:extension base="Type"/>
          </xs:complexContent>
     </xs:complexType>
     <xs:complexType name="Boolean">
          <xs:complexContent>
               <xs:extension base="Type"/>
          </xs:complexContent>
     </xs:complexType>
     <xs:complexType name="Assign">
          <xs:complexContent>
               <xs:extension base="Expr">
                    <xs:sequence>
                         <xs:element name="Id" type="xs:string"/>
                         <xs:element name="Rhs" type="Expr"/>
                    </xs:sequence>
               </xs:extension>
          </xs:complexContent>
     </xs:complexType>
</xs:schema>

OO API

class Expr : XTypedElement
{
   	constructor	  	Expr();
   	explicit cast	  	Expr(System.Xml.Linq.XElement xe);
}
class Constant : Expr
{
   	constructor	  	Constant();
   	constructor	  	Constant(int? Integer);
   	constructor	  	Constant(bool? Boolean);
   	explicit cast	  	Constant(System.Xml.Linq.XElement xe);
   	property	  	int?	  	Integer	  	{ get; set; }
   	property	  	bool?	  	Boolean	  	{ get; set; }
}
class Variable : Expr
{
   	constructor	  	Variable();
   	explicit cast	  	Variable(System.Xml.Linq.XElement xe);
   	property	  	string	  	Id	  	{ get; set; }
}
class Block : Expr
{
   	constructor	  	Block();
   	explicit cast	  	Block(System.Xml.Linq.XElement xe);
   	property	  	IList<Decl>	  	Decl	  	{ get; set; }
   	property	  	IList<Expr>	  	Expr	  	{ get; set; }
}
class Decl : XTypedElement
{
   	constructor	  	Decl();
   	explicit cast	  	Decl(System.Xml.Linq.XElement xe);
   	property	  	string	  	Id	  	{ get; set; }
   	property	  	Type	  	Type	  	{ get; set; }
}
class Type : XTypedElement
{
   	constructor	  	Type();
   	explicit cast	  	Type(System.Xml.Linq.XElement xe);
}
class Integer : Type
{
   	constructor	  	Integer();
   	explicit cast	  	Integer(System.Xml.Linq.XElement xe);
}
class Boolean : Type
{
   	constructor	  	Boolean();
   	explicit cast	  	Boolean(System.Xml.Linq.XElement xe);
}
class Assign : Expr
{
   	constructor	  	Assign();
   	explicit cast	  	Assign(System.Xml.Linq.XElement xe);
   	property	  	string	  	Id	  	{ get; set; }
   	property	  	Expr	  	Rhs	  	{ get; set; }
}
class Program : XTypedElement
{
   	constructor	  	Program();
   	constructor	  	Program(Block content);
   	explicit cast	  	Program(System.Xml.Linq.XElement xe);
   	property	  	Block	  	Content	  	{ get;  }
   	property	  	IList<Decl>	  	Decl	  	{ get; set; }
   	property	  	IList<Expr>	  	Expr	  	{ get; set; }
}
⚠️ **GitHub.com Fallback** ⚠️