The document discusses code generation from an XSD schema containing complex types. It analyzes the ComplexType "AdvResTicketingType" which has a nested structure including elements, sequences, and attributes. The generator represents this structure using an intermediate "Structure Element Repository" format. It generates classes for the complex type and its dependent types, ensuring optional elements and attributes are handled correctly. The generator also produces internal classes to represent sequences and elements within the complex type.
3. INTRODUCTION
In previous articles in this series, we looked at the SimpleType and its related XSD
elements, W3C Primitives and type restrictions, as well as the AttributeGroup and
its contained Attribute elements.
In this article we will look in detail at a, necessarily, limited selection of ComplexType
types (xs:complexType) from the second version of Open Travel
(www.opentravel.org) schema sets for the year 2014 – 2014B. The generation will
be performed by Schema Studio.
THE COMPLEXTYPE
The W3C ComplexType has the general definition:
<complexType
id=ID
name=NCName
abstract=true|false
mixed=true|false
block=(#all|list of (extension|restriction))
final=(#all|list of (extension|restriction))
any attributes>
(annotation?,
(simpleContent|complexContent|((group|all|choice|sequence)?,
((attribute|attributeGroup)*,anyAttribute?) ) ) )
</complexType>
To explore the generation of code from ComplexType definitions, we will be using, as
in previous articles, examples from the Open Travel Schema set.
CompanyNameType
This ComplexType, drawn from OTA_CommonType.xsd schema, has the form:
<xs:complexType name="CompanyNameType">
<xs:annotation>
<xs:documentation source="Description" xml:lang="en">Identifies a company by name.
</xs:documentation>
</xs:annotation>
<xs:simpleContent>
<xs:extension base="StringLength0to128">
<xs:attributeGroup ref="CompanyID_AttributesGroup">
<xs:annotation>
<xs:documentation source="Description" xml:lang="en">Provides detailed information on
a company.
</xs:documentation>
</xs:annotation>
</xs:attributeGroup>
<xs:attribute name="Division" type="StringLength1to32" use="optional">
<xs:annotation>
4. 2
<xs:documentation source="Description" xml:lang="en">The division name or ID with
which the contact is associated.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Department" type="StringLength1to32" use="optional">
<xs:annotation>
<xs:documentation source="Description" xml:lang="en">The department name or ID with
which the contact is associated.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
In this case, we can picture the type as having the following structure:
As can be seen, the structure appears quite straightforward. However, our
generator needs to understand the SimpleContent/Extension idiom and the resultant
code needs to have access to some other types from the Open Travel ecosystem,
namely StringLength0to128, CompanyID_AttributesGroup and StringLength1to32, in
order for the CompanyNameType type to be a buildable entity. These additional types
are set out in the following table.
Type Name Form Location
StringLength0to128 SimpleType, Pattern Restriction OTA_SimpleTypes.xsd
CompanyID_AttributesGroup AttributeGroup OTA_CommonTypes.xsd
StringLength1to32 SimpleType, Pattern Restriction OTA_SimpleTypes.xsd
The SimpleType types are straightforward and, as we covered in an earlier article,
are readily generated by Schema Studio. The AttributeGroup,
CompanyID_AttributesGroup, has the following definition:
Global ComplexType - CompanyNameType
SimpleContent
Extension – base: StringLength0to128
AttributeGroup – Ref: CompanyID_AttributesGroup
Attribute – Division Type: StringLength1to32 (optional)
Attribute – Department Type: StringLength1to32 (optional)
5. 3
<xs:attributeGroup name="CompanyID_AttributesGroup">
<xs:annotation>
<xs:documentation source="Description" xml:lang="en">Provides detailed information on a
company.
</xs:documentation>
</xs:annotation>
<xs:attribute name="CompanyShortName" type="StringLength1to32" use="optional">
<xs:annotation>
<xs:documentation source="Description" xml:lang="en">Used to provide the company common
name.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="TravelSector" type="OTA_CodeType" use="optional">
<xs:annotation>
<xs:documentation source="Description" xml:lang="en">The travel sector the company is
associated with, such as air, car and hotel. Refer to OpenTravel Code List Travel Sector (TVS).
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Code" type="StringLength1to16" use="optional">
<xs:annotation>
<xs:documentation source="Description" xml:lang="en">Identifies a company by the company
code.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="CodeContext" type="StringLength1to32" use="optional">
<xs:annotation>
<xs:documentation source="Description" xml:lang="en">Identifies the context of the
identifying code, such as DUNS, IATA or internal code, etc.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="CountryCode" type="ISO3166" use="optional">
<xs:annotation>
<xs:documentation source="Description" xml:lang="en"> The country location of the company
headquarters.
</xs:documentation>
<xs:documentation source="Example" xml:lang="en">Example: us
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
And the types referenced are set out in the following table:
Type Name Form Location
StringLength1to32 SimpleType, Pattern Restriction OTA_SimpleTypes.xsd
OTA_CodeType SimpleType, Pattern Restriction OTA_SimpleTypes.xsd
StringLength1to16 SimpleType, Pattern Restriction OTA_SimpleTypes.xsd
StringLength1to32 SimpleType, Pattern Restriction OTA_SimpleTypes.xsd
ISO3166 SimpleType, Pattern Restriction OTA_SimpleTypes.xsd
As noted above all these types need to be available in order to build
CompanyID_AttributesGroup and hence CompanyNameType.
6. 4
Given that we have indeed generated all the dependent types noted above, the
execution of Schema Studio to generate CompanyNameType looks as:
7. 5
AdvResTicketingType
Let us now look at a more challenging ComplexType case, AdvResTicketingType, from
the OTA_AirCommonTypes.xsd schema.
This type has the form:
<xs:complexType name="AdvResTicketingType">
<xs:annotation>
<xs:documentation xml:lang="en">Container used to hold information regarding advance
reservation and/or advance ticketing.
</xs:documentation>
</xs:annotation>
<xs:sequence minOccurs="0">
<xs:element name="AdvReservation" minOccurs="0">
<xs:annotation>
<xs:documentation xml:lang="en">Specifies constraints on when advance reservations can be
made.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="LatestTimeOfDay" type="TimeOrDateTimeType" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">The time of day by which reservations must be made
on the last day that advance reservations can be made.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="LatestPeriod" type="NumericStringLength1to3" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">The amount of elapsed time or number of occurrences
of a day of the week before departure needed to satisfy an advance reservation requirement.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="LatestUnit" type="StayUnitType" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">The unit of elapsed time or the day of the week
to be applied to the LatestPeriod value.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="AdvTicketing" minOccurs="0">
<xs:annotation>
<xs:documentation xml:lang="en">Specifies advance ticketing restrictions.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="FromResTimeOfDay" type="TimeOrDateTimeType" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">The time of day after reservations are made by
which a ticket must be purchased.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="FromResPeriod" type="NumericStringLength1to3" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">A length of time expressed as either an amount
of time or the number of occurrences of a day of the week after reservations are made that a ticket
must be purchased.
8. 6
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="FromResUnit" type="StayUnitType" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">The unit of elapsed time or the day of the week
to be applied to the period after reservation are made that a ticket must be purchased.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="FromDepartTimeOfDay" type="TimeOrDateTimeType" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">The time of day prior to departure when that a
ticket must be purchased.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="FromDepartPeriod" type="NumericStringLength1to3" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">A length of time expressed as either an amount
of time or the number of occurrences of a day of the week before departure that a ticket must be
purchased.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="FromDepartUnit" type="StayUnitType" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">The unit of elapsed time or the day of the week
to be applied to the period before departure that a ticket must be purchased.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="AdvResInd" type="xs:boolean">
<xs:annotation>
<xs:documentation xml:lang="en">Indicator for identifying whether or not advance
reservation restrictions are involved in the request or response.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="AdvTicketingInd" type="xs:boolean" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Indicator for identifying whether or not advance
ticketing restrictions are involved in the request or response.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="RequestedTicketingDate" type="DateOrDateTimeType" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">The date a traveller wishes to ticket their reservation.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
Here we see quite a structure of elements, an optional Sequence containing an
Element which in turn contains a (local) ComplexType. We also see Attribute
elements both within the (global) ComplexType as well as in the (local) ComplexType.
How can we make sense of this structure? Perhaps the diagram below can help to
show the structural relationships between the parts:
9. 7
In this representation the nested character of the ComplexType can be more clearly
observed. In fact the representation above reflects the intermediate form used by
our generator, the so-called Structure Element (SE) Repository. It is from this form
that the concrete code generation is performed.
Some of the elements in the type definition have minOccurs attributes set, whilst
others have “optional=true”. Whilst our intermediate form captures these aspects,
the eventual code also needs to reflect these different ways of indicating optionality.
There are several dependent types that need to be available if we want our
ComplexType to be buildable. These are summarised in the following table:
Global ComplexType - AdvResTicketingType
Sequence – (optional)
Element – AdvReservation (optional)
ComplexType
Attribute – LatestTimeOfDay Type: TimeOrDateTimeType (optional)
Attribute – LatestPeriod Type: NumericStringLength1to3 (optional)
Attribute – LatestUnit Type: StayUnitType (optional)
Element – AdvTicketing (optional)
ComplexType
Attribute – FromResTimeOfDay Type: TimeOrDateTimeType (optional)
Attribute – FromResPeriod Type: NumericStringLength1to3 (optional)
Attribute – FromResUnit Type: StayUnitType (optional)
Attribute – FromDepartTimeOfDay Type: TimeOrDateTimeType (optional)
Attribute – FromDepartPeriod Type: NumericStringLength1to3 (optional)
Attribute – FromDepartUnit Type: StayUnitType (optional)
Attribute – AdvResInd Type: xs:boolean (optional)
Attribute – AdvTicketingInd Type: xs:boolean (optional)
Attribute – RequestedTicketingDate Type: DateOrDateTimeType (optional)
10. 8
Type Name Form Location
TimeOrDateTimeType SimpleType, union of xs:date,
xs:dateTime, xs:time
OTA_SimpleTypes.xsd
NumericStringLength1to3 SimpleType, Restriction, Pattern OTA_SimpleTypes.xsd
StayUnitType SimpleType, Restriction,
Enumeration
OTA_AirCommonTypes.xsd
xs:boolean XSD primitive, Restriction, Pattern -
DateOrDateTimeType SimpleType, union of xs:date,
xs:dateTime
OTA_SimpleTypes.xsd
How might we proceed?
Let us look at some specific structures that need to be considered in the
architecture of our generator.
Dealing with the Sequence
In general, the W3C Sequence has the general definition of
<x:sequence
id=xs:ID
maxOccurs=(nonNegativeInteger|unbounded)
minOccurs=nonNegativeInteger
any attributes>
(annotation?,(xs:element|xs:group|xs:choice|xs:sequence|xs:any)*)
</xs:sequence>
In this definition we can see the role of the W3C Primitive, NonNegativeInteger, in
defining min-/max-Occurs values. Also, in our generation process, we need to
interpret the meaning of “unbounded”.
The Sequence contained in the generated class AdvResTicketingType is instantiated
in the default constructor as follows:
11. 9
This class also exposes a pair of type-specific methods that allow the containing
application, for example in our case a test class, to configure the eventual optional
(type-specific) elements within the Sequence.
This concrete, synthetically named, Sequence class, AdvResTicketingTypeSEQ,is
necessarily an internal class, in our case contained within the
AdvResTicketingType.cs file. Within each method, we add a specific named type to
the sequence. These elements are represented, again, as internal classes in
AdvResTicketingType.cs, and have the synthetic names, AdvReservationEL and
AdvTicketingEL.
In generational terms, this means that the top-level CodeTypeDeclaration (CTD)
object has an additional Members added representing the Sequence and Element
CTDs.
The base class for our Sequence, W3cSequence, has the form suggested by this
snippet:
12. 10
Here we can see that at its core is a so-called GuardedList<T>, a generic C# list
type, which accepts any object which is based on W3cTypeBase, and permits a lower-
and upper-bound on the list items count to be specified.
All the types in our generated type ecosystem have an eventual base class of
W3cTypeBase. The GuardedList<T> has a base class of List<T> and inherits all the
operational characteristics of this basic C# type.
The GuardedList<T> content object is instantiated with its default W3C min-/max-
Occurs of (1,1), these being of type W3cNonNegativeInteger.
13. 11
Dealing with the Local Element
The W3C Local Element has the general definition of:
<xs:element
block=(#all | list of(“extension”|”restriction|”substitution”))
default=xs:string
fixed=xs:string
form=(“qualified”|”unqualified”)
id=xs:ID
maxOccurs=(nonNegativeInteger|unbounded):”1”
minOccurs=nonNegativeInteger:”1”
name=xs:NCName
nillable=xs:Boolean:”false”
ref=xs:QName
type=xs:QName
any attributes>
(annotation?,(xs:simleType|xs:ComplexType)?,
(xs:unique|xs:key|xs:keyRef)* )
</xs:element>
In our case, the Sequence in AdvResTicketingType contains, as we saw above, two
local elements which we gave the synthetic names of AdvReservationEL and
AdvTicketingEL.
These, like the Sequence, are generated as internal classes in the file
AdvResTicketingType.cs. As both types are structurally identical, we will look at only
one, AdvReservationEL.
The default constructor for this class takes the form:
As we saw in the case of the Sequence, this class has a general base class,
specifically W3cLocalElement.
14. 12
The default constructor instantiates the anonymous inner ComplexType, and this is
represented as an internal class (to AdvResTicketingType.cs) blessed with a
synthetic name, AdvReservationCT. This inner type is accessed by an appropriately
named Property:
Dealing with the Local Complex Type
In general the W3C Local ComplexType has the general definition of:
<xs:complexType
id=xs:ID
mixed=xs:boolean:”false”
any attributes>
(annotation?,
(xs:simpleContent|xs:ComplexContent|
(xs:group|xs:all|xs:choice|xs:sequence)?,
((xs:attribute|xs:AttributeGroup)*, xs:anyAttribute?))))
</xs:complexType >
Continuing with the case of AdvReservationEL, this local Element contains a
synthetically named local ComplexType, AdvReservationCT, which has the default
constructor as shown in this fragment:
15. 13
This, as in the other local entity cases, is generated as an internal class within the
file AdvResTicketingType.cs.
In this type we see a group of Attribute elements, all of which are optional, being
appropriately instantiated. It should be noted that the Attribute LatestUnit has a
type defined as StayUnitType, another type specified in the “air” silo of Open
Travel. The generator detects that this is indeed a named type in the current silo
and furthermore that it is a type with an enumeration restriction. The value
assigned is the 0’th value of the enumeration as expressed in the associated
XElement.
The production of the code for AdvResTicketingType, can be seen in the screenshot
of Schema Studio below:
16. 14
REMARKS
In this article, we have looked at a couple of styles of ComplexType classes as
emitted by our generator, all generated from definitions in the Open Travel 2014B
specification. Of course, as indicated in the opening section, there are many more
forms of ComplexType that could be shown.
The configuration of Schema Studio allows us to specify if the generated classes
should have appropriate methods to serialize/deserialize class instances. The topic
of serialization/deserialization is pended for a later article.
The documentation for the generated ComplexType types, and their inner classes, is
provided in the Class Documentation Appendix below. Corresponding tests are
provided in the Unit Test Appendix.
Also following is a summary of the associated types which needed to be available,
for example in our unit test project to build the ComplexType types we have been
looking at.
17. 15
APPENDIX: CLASS DOCUMENTATION
One of the key assets for a developer when using a class library is documentation.
This appendix gives an overview of the documentation available from the generated
types we saw in the previous sections.
It should be noted that the types we consider here are but a small subset of all the
types that can be generated from the OpenTravel/OTA/V2014B Schema set.
SimpleType Name Content-Type XSD Comment
ComanyNameType ComplexType with
SimpleContent/Extension
Identifies a company by name.
AdvResTicketingType ComplexType with
Sequence/ComplexType
Container used to hold information
regarding advance reservation and/or
advance ticketing.
AdvResTicketingTypeSEQ Inner Sequence class of
AdvResTicketingType
-
AdvReservationEL Optional Element within
AdvResTicketingTypeSEQ
-
AdvReservationCT Local ComplexType
within AdvReservationEL
-
AdvTicketingEL Optional Element within
AdvResTicketingTypeSEQ
-
AdvTicketingCT Local ComplexType
within AdvTicketingEL
-
StayUnitType SimpleType with
Enumeration Restriction
Defines the 'Units' that can be applied to
Stay restrictions.
CompanyID_AttributesGroup AttributeGroup
containing Attributes
Provides detailed information on a
company.
64. 62
APPENDIX: UNIT TESTS
As part of our generation process, we need to assert that the emitted classes meet
their specification. This we do using unit testing.
In this section, we illustrate the tests applied to the ComplexType classes noted in
the previous sections.
Index
CompanyNameType
AdvResTicketingType
65. 63
CompanyNameType
Now we have our ComplexType generated let’s ensure that all is ok via Unit Tests.
Two groups of tests are performed “SimpleAssign” and “Operations”.
[TestMethod]
public void CompanyNameType_SimpleAssign()
{
CompanyNameType = new CompanyNameType();
Assert.IsNotNull(companyNameType, "object was null");
Assert.IsFalse(companyNameType.DivisionSpecified, "DivisionSpecified not as expected");
Assert.IsFalse(companyNameType.DepartmentSpecified, "DepartmentSpecified not as expected");
Assert.IsFalse(companyNameType.CompanyID_AttributesGroup.CompanyShortNameSpecified,
"CompanyShortNameSpecified not as expected");
Assert.IsFalse(companyNameType.CompanyID_AttributesGroup.TravelSectorSpecified,
"TravelSectorSpecified not as expected");
Assert.IsFalse(companyNameType.CompanyID_AttributesGroup.CodeSpecified,
"CodeSpecified not as expected");
Assert.IsFalse(companyNameType.CompanyID_AttributesGroup.CodeContextSpecified,
"CodeContextSpecified not as expected");
Assert.IsFalse(companyNameType.CompanyID_AttributesGroup.CountryCodeSpecified,
"CountryCodeSpecified not as expected");
companyNameType.Division = new StringLength1to32() { Text = "Research" };
Assert.IsTrue(companyNameType.DivisionSpecified, "DivisionSpecified not as expected");
companyNameType.Department = new StringLength1to32() { Text = "OpenTravel" };
Assert.IsTrue(companyNameType.DepartmentSpecified, "DepartmentSpecified not as expected");
companyNameType.CompanyID_AttributesGroup.CompanyShortName =
new StringLength1to32() { Text = "JMT" };
Assert.IsTrue(companyNameType.CompanyID_AttributesGroup.CompanyShortNameSpecified,
"CompanyShortNameSpecified not as expected");
companyNameType.CompanyID_AttributesGroup.TravelSector =
new OTA_CodeType() { Text = "101.EQP" };
Assert.IsTrue(companyNameType.CompanyID_AttributesGroup.TravelSectorSpecified,
"TravelSectorSpecified not as expected");
companyNameType.CompanyID_AttributesGroup.Code =
new StringLength1to16() { Text = "BB-556" };
Assert.IsTrue(companyNameType.CompanyID_AttributesGroup.CodeSpecified,
"CodeSpecified not as expected");
companyNameType.CompanyID_AttributesGroup.CodeContext =
new StringLength1to32() { Text = "DUNS IATA" };
Assert.IsTrue(companyNameType.CompanyID_AttributesGroup.CodeContextSpecified,
"CodeContextSpecified not as expected");
companyNameType.CompanyID_AttributesGroup.CountryCode =
new ISO3166() { Text = "UK" };
Assert.IsTrue(companyNameType.CompanyID_AttributesGroup.CountryCodeSpecified,
"CountryCodeSpecified not as expected");
}
Which assigned valid values to the various properties and ensures that the flags
that indicate if an optional value has been set or not, are correctly handled.
[TestMethod]
public void CompanyNameType_Operations()
{
CompanyNameType companyNameType1 = new CompanyNameType();
66. 64
Assert.IsNotNull(companyNameType1, "object was null");
companyNameType1.Division = new StringLength1to32() { Text = "Research" };
companyNameType1.Department = new StringLength1to32() { Text = "OpenTravel" };
companyNameType1.CompanyID_AttributesGroup.CompanyShortName =
new StringLength1to32() { Text = "JMT" };
companyNameType1.CompanyID_AttributesGroup.TravelSector =
new OTA_CodeType() { Text = "101.EQP" };
companyNameType1.CompanyID_AttributesGroup.Code =
new StringLength1to16() { Text = "BB-556" };
companyNameType1.CompanyID_AttributesGroup.CodeContext =
new StringLength1to32() { Text = "DUNS IATA" };
companyNameType1.CompanyID_AttributesGroup.CountryCode =
new ISO3166() { Text = "UK" };
CompanyNameType companyNameType2 = new CompanyNameType();
Assert.IsNotNull(companyNameType2, "object was null");
companyNameType2.Division =
new StringLength1to32() { Text = "Sales and Marketing" };
companyNameType2.Department =
new StringLength1to32() { Text = "OpenTravel" };
companyNameType2.CompanyID_AttributesGroup.CompanyShortName =
new StringLength1to32() { Text = "JMT" };
companyNameType2.CompanyID_AttributesGroup.TravelSector =
new OTA_CodeType() { Text = "102.EQP" };
companyNameType2.CompanyID_AttributesGroup.Code =
new StringLength1to16() { Text = "BB-558" };
companyNameType2.CompanyID_AttributesGroup.CodeContext =
new StringLength1to32() { Text = "DUNS IATA" };
companyNameType2.CompanyID_AttributesGroup.CountryCode =
new ISO3166() { Text = "UK" };
Assert.IsTrue(companyNameType1 != companyNameType2, "!= operator failed");
Assert.IsFalse(companyNameType1 == companyNameType2, "== operator failed");
Assert.IsFalse(companyNameType1.Equals( companyNameType2 ), "Equals method failed");
CompanyNameType companyNameType3 = new CompanyNameType(companyNameType2);
Assert.IsTrue(companyNameType3.Division.Text == "Sales and Marketing",
"Division after CopyCtor NOK");
Assert.IsTrue(companyNameType3.Department.Text == "OpenTravel",
"Department after CopyCtor NOK");
Assert.IsTrue(companyNameType3.CompanyID_AttributesGroup.CompanyShortName.Text == "JMT",
"CompanyID_AttributesGroup.CompanyShortName after CopyCtor NOK");
Assert.IsTrue(companyNameType3.CompanyID_AttributesGroup.TravelSector.Text == "102.EQP",
"CompanyID_AttributesGroup.TravelSector after CopyCtor NOK");
Assert.IsTrue(companyNameType3.CompanyID_AttributesGroup.Code.Text == "BB-558",
"CompanyID_AttributesGroup.Code after CopyCtor NOK");
Assert.IsTrue(companyNameType3.CompanyID_AttributesGroup.CodeContext.Text == "DUNS IATA",
"CompanyID_AttributesGroup.CodeContext after CopyCtor NOK");
Assert.IsTrue(companyNameType3.CompanyID_AttributesGroup.CountryCode.Text == "UK",
"CompanyID_AttributesGroup.CountryCode after CopyCtor NOK");
}
In this “operations” test we ensure that the “==”, “!=” operators as well as the
“Equals()” method and copy constructor work as expected.
For these more complex types from W3C Schema, we should assert that the string
representation, expressed via ToString(), is as expected. We perform this validation
in the following test:
67. 65
[TestMethod]
public void CompanyNameType_ToString()
{
CompanyNameType companyNameType1 = new CompanyNameType();
Assert.IsNotNull(companyNameType1, "object was null");
companyNameType1.Division =
new StringLength1to32() { Text = "Research" };
companyNameType1.Department =
new StringLength1to32() { Text = "OpenTravel" };
companyNameType1.CompanyID_AttributesGroup.CompanyShortName =
new StringLength1to32() { Text = "JMT" };
companyNameType1.CompanyID_AttributesGroup.TravelSector =
new OTA_CodeType() { Text = "101.EQP" };
companyNameType1.CompanyID_AttributesGroup.Code =
new StringLength1to16() { Text = "BB-556" };
companyNameType1.CompanyID_AttributesGroup.CodeContext =
new StringLength1to32() { Text = "DUNS IATA" };
companyNameType1.CompanyID_AttributesGroup.CountryCode =
new ISO3166() { Text = "UK" };
string s = companyNameType1.ToString();
string tmp = ""name"=CompanyID_AttributesGroup, "type"="xs:attributeGroup", "+
""name"="CompanyShortName","type"="StringLength1to32","text"="JMT", "+
""name"="TravelSector","type"="OTA_CodeType","text"="101.EQP", "+
""name"="Code","type"="StringLength1to16","text"="BB-556", "+
""name"="CodeContext","type"="StringLength1to32","text"="DUNS IATA", "+
""name"="CountryCode","type"="ISO3166","text"="UK", "+
""name"="Division", "type"="StringLength1to32","text"="Research", "+
""name"="Department", "type"="StringLength1to32","text"="OpenTravel"";
Assert.IsTrue(s.Equals(tmp), "Equals method failed");
}
Of course, to execute these tests at all, we must have all the dependent types
available, and these have also need to have been subjected to similar tests.
68. 66
AdvResTicketingType
As above, our tests are defined in three blocks “SimpleAssign”, “Operations” and
“ToString”.
[TestMethod]
public void AdvResTicketingType_SimpleAssign()
{
AdvResTicketingType art1 = new AdvResTicketingType();
Assert.IsNotNull(art1, "object was null");
Assert.IsTrue(Convert.ToInt32(art1.Sequence.MinOccurs.Text) == 0,
"minOccurs of sequence not as expected");
Assert.IsTrue(art1.Sequence.MinOccursSpecified,
"Sequence MinOccursSpecified was not as expected");
Assert.IsTrue(art1.Sequence.MaxOccursSpecified,
"Sequence MaxOccursSpecified was not as expected");
Assert.IsTrue(Convert.ToInt32(art1.Sequence.MaxOccurs.Text) == Int32.MaxValue,
"maxOccurs of sequence not as expected");
// ----------------------------------------------------------------------------
art1.AdvResInd.Text = "true";
Assert.IsFalse(art1.AdvTicketingIndSpecified,
"AdvTicketingIndSpecified not as expected");
Assert.IsFalse(art1.RequestedTicketingDateSpecified,
"RequestedTicketingDateSpecified not as expected");
art1.AdvTicketingInd = W3cAttribute.CreateSetText(art1.AdvTicketingInd, "false");
Assert.IsTrue(art1.AdvTicketingIndSpecified,
"AdvTicketingIndSpecified not as expected");
art1.RequestedTicketingDate =
new DateOrDateTimeType() { Text = "2022-12-05T08:15:30-05:00" };
Assert.IsTrue(art1.RequestedTicketingDateSpecified,
"RequestedTicketingDateSpecified not as expected");
// ----------------------------------------------------------------------------
AdvReservationEL advReservation = new AdvReservationEL();
Assert.IsFalse(advReservation.AdvReservationCT.LatestTimeOfDaySpecified,
"AdvReservationCT.LatestTimeOfDaySpecified not as expected");
Assert.IsFalse(advReservation.AdvReservationCT.LatestPeriodSpecified,
"AdvReservationCT.LatestPeriodSpecified not as expected");
Assert.IsFalse(advReservation.AdvReservationCT.LatestUnitSpecified,
"AdvReservationCT.LatestUnitSpecified not as expected");
advReservation.AdvReservationCT.LatestTimeOfDay =
new TimeOrDateTimeType() { Text = "17:30:00" };
Assert.IsTrue(advReservation.AdvReservationCT.LatestTimeOfDaySpecified,
"AdvReservationCT.LatestTimeOfDaySpecified not as expected");
advReservation.AdvReservationCT.LatestPeriod =
new NumericStringLength1to3() { Text = "12" };
Assert.IsTrue(advReservation.AdvReservationCT.LatestPeriodSpecified,
"AdvReservationCT.LatestPeriodSpecified not as expected");
advReservation.AdvReservationCT.LatestUnit = StayUnitType.eHours;
Assert.IsTrue(advReservation.AdvReservationCT.LatestUnitSpecified,
"AdvReservationCT.LatestUnitSpecified not as expected");
art1.AddSequenceItem(advReservation);
Assert.IsTrue(art1.Sequence.Content.Items[0] is AdvReservationEL,
"0th element not of expected type");
Assert.IsTrue(art1.Sequence.Content.Count == 1,
69. 67
"sequence count not as expected");
// ----------------------------------------------------------------------------
AdvTicketingEL advTicketing = new AdvTicketingEL();
Assert.IsFalse(advTicketing.AdvTicketingCT.FromResTimeOfDaySpecified,
"AdvReservationCT.FromResTimeOfDaySpecified not as expected");
Assert.IsFalse(advTicketing.AdvTicketingCT.FromResPeriodSpecified,
"AdvReservationCT.FromResPeriodSpecified not as expected");
Assert.IsFalse(advTicketing.AdvTicketingCT.FromResUnitSpecified,
"AdvReservationCT.FromResUnitSpecified not as expected");
Assert.IsFalse(advTicketing.AdvTicketingCT.FromDepartTimeOfDaySpecified,
"AdvReservationCT.FromDepartTimeOfDaySpecified not as expected");
Assert.IsFalse(advTicketing.AdvTicketingCT.FromDepartPeriodSpecified,
"AdvReservationCT.FromDepartPeriodSpecified not as expected");
Assert.IsFalse(advTicketing.AdvTicketingCT.FromDepartUnitSpecified,
"AdvReservationCT.FromDepartUnitSpecified not as expected");
advTicketing.AdvTicketingCT.FromResTimeOfDay =
new TimeOrDateTimeType() { Text = "14:45:00" };
Assert.IsTrue(advTicketing.AdvTicketingCT.FromResTimeOfDaySpecified,
"AdvReservationCT.FromResTimeOfDaySpecified not as expected");
advTicketing.AdvTicketingCT.FromResPeriod =
new NumericStringLength1to3() { Text = "8" };
Assert.IsTrue(advTicketing.AdvTicketingCT.FromResPeriodSpecified,
"AdvReservationCT.FromResPeriodSpecified not as expected");
advTicketing.AdvTicketingCT.FromResUnit = StayUnitType.eWED;
Assert.IsTrue(advTicketing.AdvTicketingCT.FromResUnitSpecified,
"AdvReservationCT.FromResUnitSpecified not as expected");
advTicketing.AdvTicketingCT.FromDepartTimeOfDay =
new TimeOrDateTimeType() { Text = "17:00:00" };
Assert.IsTrue(advTicketing.AdvTicketingCT.FromDepartTimeOfDaySpecified,
"AdvReservationCT.FromDepartTimeOfDaySpecified not as expected");
advTicketing.AdvTicketingCT.FromDepartPeriod =
new NumericStringLength1to3() { Text = "8" };
Assert.IsTrue(advTicketing.AdvTicketingCT.FromDepartPeriodSpecified,
"AdvReservationCT.FromDepartPeriodSpecified not as expected");
advTicketing.AdvTicketingCT.FromDepartUnit = StayUnitType.eHours;
Assert.IsTrue(advTicketing.AdvTicketingCT.FromDepartUnitSpecified,
"AdvReservationCT.FromDepartUnitSpecified not as expected");
art1.AddSequenceItem(advTicketing);
Assert.IsTrue(art1.Sequence.Content.Items[1] is AdvTicketingEL,
"0th element not of expected type");
Assert.IsTrue(art1.Sequence.Content.Count == 2,
"sequence count not as expected");
}
and the “Operations” set is as:
[TestMethod]
public void AdvResTicketingType_Operations()
{
AdvResTicketingType art1 = new AdvResTicketingType();
Assert.IsNotNull(art1, "object was null");
art1.AdvResInd.Text = "true";
Assert.IsFalse(art1.AdvTicketingIndSpecified,
"AdvTicketingIndSpecified not as expected");
Assert.IsFalse(art1.RequestedTicketingDateSpecified,
"RequestedTicketingDateSpecified not as expected");
70. 68
art1.AdvTicketingInd = W3cAttribute.CreateSetText(art1.AdvTicketingInd, "false");
Assert.IsTrue(art1.AdvTicketingIndSpecified,
"AdvTicketingIndSpecified not as expected");
art1.RequestedTicketingDate =
new DateOrDateTimeType() { Text = "2022-12-05T08:15:30-05:00" };
Assert.IsTrue(art1.RequestedTicketingDateSpecified,
"RequestedTicketingDateSpecified not as expected");
// ----------------------------------------------------------------------------
AdvResTicketingType art2 = new AdvResTicketingType();
Assert.IsNotNull(art2, "object was null");
art2.AdvResInd.Text = "false";
art2.AdvTicketingInd =
W3cAttribute.CreateSetText(art1.AdvTicketingInd, "false");
art2.RequestedTicketingDate =
new DateOrDateTimeType() { Text = "2023-01-10T10:15:30-05:00" };
Assert.IsTrue(art1 != art2, "!= operator failed");
Assert.IsFalse(art1 == art2, "!= operator failed");
Assert.IsFalse(art1.Equals(art2), "Equals method failed");
// -----------------------------------------------------------------------------
AdvResTicketingType art3 = (AdvResTicketingType)art1.Clone();
Assert.IsTrue(art3 == art1, "== operator failed");
Assert.IsTrue(art3.Equals(art1), "Equals method failed");
Assert.IsFalse(art3 != art1, "!= operator failed");
// -----------------------------------------------------------------------------
AdvResTicketingType art4 = new AdvResTicketingType();
art4.AdvResInd.Text = "false";
art4.AdvTicketingInd.Text = "true";
art4.RequestedTicketingDate =
new DateOrDateTimeType() { Text = "2023-07-16" };
AdvResTicketingType art5 = (AdvResTicketingType)art4.Clone();
art5.AdvResInd.Text = "true";
art5.AdvTicketingInd.Text = "false";
art5.RequestedTicketingDate =
new DateOrDateTimeType() { Text = "2023-08-16" };
Assert.IsFalse(art4 == art5, "== operator failed");
Assert.IsTrue(art4 != art5, "!= operator failed");
Assert.IsFalse(art4.Equals(art5), "Equals method failed");
}
and the “ToString” set:
[TestMethod]
public void AdvResTicketingType_ToString()
{
AdvResTicketingType art1 = new AdvResTicketingType();
Assert.IsNotNull(art1, "object was null");
art1.AdvResInd.Text = "true";
art1.AdvTicketingInd =
W3cAttribute.CreateSetText(art1.AdvTicketingInd, "false");
art1.RequestedTicketingDate =
new DateOrDateTimeType() { Text = "2022-12-05T08:15:30-05:00" };
71. 69
// --------------------------------------------------------------------------
{
AdvReservationEL item = new AdvReservationEL();
item.AdvReservationCT.LatestTimeOfDay =
new TimeOrDateTimeType() { Text = "17:30:00" };
item.AdvReservationCT.LatestPeriod =
new NumericStringLength1to3() { Text = "12" };
item.AdvReservationCT.LatestUnit =
StayUnitType.eDays;
art1.AddSequenceItem(item);
string tmp =
""name"="AdvResTicketingType", "type"="xs:complexType", "+
""name"="AdvResTicketingTypeSEQ", "type"="xs:sequence",
"maxOccurs"="2147483647", "minOccurs"="0", "+
""name"="AdvReservationEL", "type"="xs:element", "minOccurs"="0",
"maxOccurs"="1", "+
""name"="AdvReservationCT", "type"="xs:complexType", "+
""name"="LatestTimeOfDay", "type"="TimeOrDateTimeType","text"="17:30:00", "+
""name"="LatestPeriod", "type"="NumericStringLength1to3","text"="12", "+
""name"="LatestUnit", "type"="LatestUnit", "text"="LatestUnit.Days", "+
""name"="AdvResInd", "type"="boolean", "text"="true", "+
""name"="AdvTicketingInd", "type"="boolean", "text"="false", "+
""name"="","type"="DateOrDateTimeType","text"="2022-12-
05T08:15:30-05:00"";
string s = art1.ToString();
Assert.IsTrue(s == tmp, "stringified form not as expected");
}
// --------------------------------------------------------------------------
{
AdvTicketingEL item = new AdvTicketingEL();
item.AdvTicketingCT.FromResTimeOfDay =
new TimeOrDateTimeType() { Text = "17:30:00" };
item.AdvTicketingCT.FromResPeriod =
new NumericStringLength1to3() { Text = "12" };
item.AdvTicketingCT.FromResUnit =
StayUnitType.eDays;
item.AdvTicketingCT.FromDepartTimeOfDay =
new TimeOrDateTimeType() { Text = "16:30:00" };
item.AdvTicketingCT.FromDepartPeriod =
new NumericStringLength1to3() { Text = "4" };
item.AdvTicketingCT.FromDepartUnit =
StayUnitType.eHours;
art1.AddSequenceItem(item);
string tmp = ""name"="AdvResTicketingType", "type"="xs:complexType", "+
""name"="AdvResTicketingTypeSEQ", "type"="xs:sequence",
"maxOccurs"="2147483647", "minOccurs"="0", "+
""name"="AdvReservationEL", "type"="xs:element", "minOccurs"="0",
"maxOccurs"="1", "+
""name"="AdvReservationCT", "type"="xs:complexType", "+
""name"="LatestTimeOfDay", "type"="TimeOrDateTimeType","text"="17:30:00", "+
""name"="LatestPeriod", "type"="NumericStringLength1to3","text"="12", "+
""name"="LatestUnit", "type"="LatestUnit", "text"="LatestUnit.Days", "+
""name"="AdvTicketingEL", "type"="xs:element", "minOccurs"="0",
"maxOccurs"="1", "+
""name"="AdvTicketingCT", "type"="xs:complexType", "+
""name"="FromResTimeOfDay","type"="TimeOrDateTimeType","text"="17:30:00", "+
72. 70
""name"="FromResPeriod","type"="NumericStringLength1to3","text"="12", "+
""name"="FromResUnit","type"="StayUnitType", "text"="StayUnitType.Days", "+
""name"="FromDepartTimeOfDay","type"="DateOrDateTimeType","text"="16:30:00", "+
""name"="FromDepartPeriod","type"="NumericStringLength1to3","text"="4", "+
""name"="FromDepartUnit","type"="StayUnitType", "text"="StayUnitType.Hours", "+
""name"="AdvResInd", "type"="boolean", "text"="true", "+
""name"="AdvTicketingInd", "type"="boolean", "text"="false", "+
""name"="","type"="DateOrDateTimeType","text"="2022-12-05T08:15:30-05:00"";
string s = art1.ToString();
Assert.IsTrue(s == tmp, "stringified form not as expected");
}
}
73. 71
APPENDIX: BASE CLASS DOCUMENTATION
In this section, we provide the documentation for the key base classes we have
used in the generated code we have seen in earlier sections, W3cGlobalComplexType ,
W3cSequence, W3cLocalElement and W3cLocalComplexType.
Index
W3cGlobalComplexType
W3cSequence
W3cLocalElement
W3cLocalComplexType
StringLength0to128
107. 105
APPENDIX: ASSOCIATED TYPES
There are several types that need to be available when building the ComplexType
types set out in the foregoing sections.
Type Name Comments Location
W3Attribute The base class for W3C Attributes -
W3cID The W3C Primitive xs:ID type -
W3cNonNegativeInteger The W3C Primitive
xs:nonNegativeInteger
-
DateOrDateTimeType A SimpleType union of xs:date and
xs:dateTime
OTA_SimpleTypes.xsd
TimeOrDateTimeType A SimpleType union of xs:date,
xs:dateTime and xs:time
OTA_SimpleTypes.xsd
NumericStringLength1to3 A SimpleType with Pattern
Restriction
OTA_SimpleTypes.xsd
StayUnitType A SimpleType with Enumeration
Restriction
OTA_AirCommonTypes.xsd
StringLength1to32 A SimpleType with min-/max-
Length Restriction
OTA_SimpleTypes.xsd
StringLength0to128 A SimpleType with min-/max-
Length Restriction
OTA_SimpleTypes.xsd
StringLength1to32 A SimpleType with min-/max-
Length Restriction
OTA_SimpleTypes.xsd
StringLength1to16 A SimpleType with min-/max-
Length Restriction
OTA_SimpleTypes.xsd
OTA_CodeType A SimpleType with Pattern
Restriction
OTA_SimpleTypes.xsd
ISO3166 A SimpleType with Pattern
Restriction
OTA_SimpleTypes.xsd
CompanyID_AttributesGroup An AttributeGroup type OTA_CommonTypes.xsd
Within the generated code of these types, where they involve W3C Primitives, such
as xs:date, the code makes use of classes such as W3cDate, etc.
All these supporting types have unit tests, but, for brevity, these are not set out
here.