Defining the Root PurchaseOrder Datatype

Defining the Items Array

The next step is to define the array of items contained within a purchase order. The following code defines the type that will represent an individual item within the purchase order. Recall that the individual Item elements within the Items array contain a combination of elements and attributes.

<Item partNumber="A1467">   <Price>23.5</Price>   <Quantity>2</Quantity> </Item>

By default, public read/writable properties defined within a .NET type are serialized as XML elements. The XmlAttribute attribute is used to indicate that a property or a field should be serialized as an attribute instead of as an element. The following code defines the partNumber attribute for the Item element definition:

public class PurchaseOrderItem {     [XmlAttribute("partNumber")]     public string       PartNumber;     public int          Quantity;     public double       Price;     public CurrencyType Currency; }

By convention, I use camel case when naming the partNumber attribute. In camel case, the first word that composes the entity name is all lowercase and the first letter of each subsequent word is capitalized. But the standard convention for public properties and fields exposed by a .NET type is Pascal case, in which the first letter of each word making up the entity name is uppercase.

By default, the name of the attribute in the serialized XML document is the name of the property or field. Because the name of the field does not match the name of the attribute, I pass the intended name of the attribute to the constructor for the XmlAttribute attribute. The value of the Name property is set to the string passed to the constructor.

The XmlAttribute attribute exposes additional properties that you can use to control how XML serialization serializes the associated property or field to an attribute. These properties are described in Table 7-6.

Table 7-6  XmlAttributeAttribute Properties

Property

Description

AttributeName

Specifies the name of the XML attribute.

DataType

Specifies the XML Schema built-in datatype in which the property or field should be encoded.

Form

Specifies whether the XML attribute must be namespace qualified. It is set to one of three values defined by the XmlSchemaForm enumeration: None, Qualified, or Unqualified.

Namespace

Specifies the XML namespace in which the attribute is defined.

The Currency element is of type CurrencyType. CurrencyType is an enumeration containing the valid currency types supported by the AcceptPO Web method. You can use the XmlEnum attribute to alter the name of an element typed to a particular enumeration. As an illustration, the following code uses the XmlEnum attribute to rename the public field for describing the currency that was used to price the item:

public class PurchaseOrderItem { [XmlAttribute("partNumber")] public string     PartNumber; public int        Quantity; public double     Price; [XmlEnum("Currency")] public CurrencyType TypeOfCurrency; }

The following code adds an array of Item elements to the PurchaseOrder class. Two attributes can be used to control how an array is serialized to XML: XmlArray and XmlArrayItems. Here is the PurchaseOrder class definition:

[XmlRoot(IsNullable=false)] public class PurchaseOrder {     [XmlElement(IsNullable=false)]     public Address BillingAddress;     [XmlElement(IsNullable=false)]     public Address ShippingAddress;     [XmlArray("Items", IsNullable=false)]     [XmlArrayItem("Item", IsNullable=false)]     public PurchaseOrderItem [] Items;     // Additional type definitions... }

The XmlArray attribute is used to control how the root element of the array is serialized. Because the purchase order is valid only if the array of Item elements is not null, the IsNullable property is set to false in the preceding code.

The XmlArrayItem attribute is used to control how each item within the array is serialized. Because none of the items within the array can be set to null, the IsNullable property of the XmlArrayItem attribute is set to false in the preceding code.

In XML serialization, by default each element within the array has the same name as the type definition. In this example, the type definition name is PurchaseOrderItem. Because the name of the elements within the Items array should be named Item, I explicitly set the name of the element.

You can also use the XmlArrayItem attribute to define arrays containing instances of a mixture of datatypes. You can do this by decorating an array with multiple XmlArrayItem attributes. The following code defines an array that can contain items of type string and int:

[XmlArrayItem("MyInt", typeof(int))] [XmlArrayItem("MyString", typeof(string))] public object [] TestArray;

The preceding code will generate the following XML datatype definition:

<element minOccurs="1" maxOccurs="1" name="TestArray" nillable="true" type="s0:ArrayOfChoice1" /> <complexType name="ArrayOfChoice1">   <sequence>     <choice minOccurs="0" maxOccurs="unbounded">       <element minOccurs="1" maxOccurs="1" name="MyInt" type="int" />        <element minOccurs="1" maxOccurs="1" name="MyString" type="string" />      </choice>   </sequence> </complexType>

Notice that the TestArray element can contain any combination of child elements of type string and int. To accept data of different types from the client, the XML mixed array is mapped to a .NET array of type Object. The compiler will not throw an error if the .NET type is set to something other than Object—say, Boolean. However, the client will receive a run-time error if the client sends an instance of an XML datatype that cannot be transformed into the underlying .NET type.

The XmlArray and XmlArrayItems attributes expose additional properties that you can use to control how an array is serialized to XML. Tables 7-7 and 7-8 describe these properties.

Table 7-7  XmlArrayAttribute Properties

Property

Description

ElementName

Specifies the name of the XML element.

Form

Specifies whether the XML element must be namespace qualified. It is set to one of three values defined by the XmlSchemaForm enumeration: None, Qualified, or Unqualified.

IsNullable

Specifies whether the value of the XML element can have its xsi:nil attribute set to true.

Namespace

Specifies the XML namespace in which the element is defined.


Table 7-8  XmlArrayItemAttribute Properties

Property

Description

DataType

Specifies the XML Schema built-in datatype in which the property or field should be encoded.

ElementName

Specifies the name of the XML element.

Form

Specifies whether the XML element must be namespace qualified. It is set to one of three values defined by the XmlSchemaForm enumeration: None, Qualified, or Unqualified.

IsNullable

Specifies whether the value of the XML element can have its xsi:nil attribute set to true.

Namespace

Specifies the XML namespace in which the element is defined.

Type

Specifies the .NET type that should be used to generate the schema that describes the element.

As I mentioned earlier, the default behavior of XML serialization is to serialize an array as a root element, where each item is contained within a child element. However, sometimes it might be necessary to specify a collection of content that is not wrapped by a root element.

You can specify that each element of an array not be wrapped within a parent element by decorating the array with the XmlElement attribute. The following example creates the BaseballTeam type, which contains one CoachName child element and any number of PlayerName child elements:

public class BaseballTeam {     public string CoachName;     [XmlElement("PlayerName")]     public string [] Players; }

The preceding .NET type definition creates the following XML datatype definition:

<complexType name="BaseballTeam">   <sequence>     <element minOccurs="1" maxOccurs="1" name="Coach" nillable="true"     type="s:string" />     <element minOccurs="0" maxOccurs="unbounded" name="PlayerName"     type="s:string" />   </sequence> </complexType>

You can also decorate an array with multiple XmlElement attributes. Doing so specifies that an instance document can contain any combination and any number of elements defined by the XmlElement attributes. The following example defines a BaseballTeam XML datatype that contains one CoachName element and any combination of PlayerName and PlayerNumber elements:

public class BaseballTeam {     public string Coach;     [XmlElement("PlayerName", typeof(string))]     [XmlElement("PlayerNumber", typeof(int))]     public string [] Players; }

The preceding .NET type definition creates the following XML datatype definition:

<complexType name="BaseballTeam">   <sequence>     <element minOccurs="1" maxOccurs="1" name="Coach" nillable="true"     type="s:string" />     <choice minOccurs="0" maxOccurs="unbounded">       <element minOccurs="1" maxOccurs="1" name="PlayerName" type="s:string" />       <element minOccurs="1" maxOccurs="1" name="PlayerNumber" type="s:int" />     </choice>   </sequence> </complexType>



Building XML Web Services for the Microsoft  .NET Platform
Building XML Web Services for the Microsoft .NET Platform
ISBN: 0735614067
EAN: 2147483647
Year: 2002
Pages: 94
Authors: Scott Short

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net