The XSD tool also knows how to
generate a an XSD from compiled types in a DLL or executable file.
When generating a schema, xsd
makes certain
assumptions about the XSD types of instance variables. For any given
CLR type, xsd
chooses an XSD type for the schema.
Table 8-2 lists each XSD type and its
corresponding common language runtime type. In the cases where more
than one XSD type maps to a single CLR type, the bold one will be
used.
XSD type |
CLR type |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Angus Hardware might have a class structure for product listings, such as is shown in Example 8-4. This code can be compiled into the library Product.dll.
using System; public class Address { public string [ ] Street; public string City; public string State; public string Zip; } public class Manufacturer { public string Name; public Address [ ] Addresses; } public class Product { public string Name; public string ProductCode; public Manufacturer Manufacturer; public DateTime DateIntroduced; public decimal UnitCost; }
When you run the command xsd Product.dll
, you get
the generated XSD shown in Example 8-5.
<?xml version="1.0" encoding="utf-8"?> <xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="Address" nillable="true" type="Address" /> <xs:complexType name="Address"> <xs:sequence> <xs:element minOccurs="0" maxOccurs="1" name="Street" type="ArrayOfString" /> <xs:element minOccurs="0" maxOccurs="1" name="City" type="xs:string" /> <xs:element minOccurs="0" maxOccurs="1" name="State" type="xs:string" /> <xs:element minOccurs="0" maxOccurs="1" name="Zip" type="xs:string" /> </xs:sequence> </xs:complexType> <xs:complexType name="ArrayOfString"> <xs:sequence> <xs:element minOccurs="0" maxOccurs="unbounded" name="string" nillable="true" type="xs:string" /> </xs:sequence> </xs:complexType> <xs:element name="Manufacturer" nillable="true" type="Manufacturer" /> <xs:complexType name="Manufacturer"> <xs:sequence> <xs:element minOccurs="0" maxOccurs="1" name="Name" type="xs:string" /> <xs:element minOccurs="0" maxOccurs="1" name="Addresses" type="ArrayOfAddress" /> </xs:sequence> </xs:complexType> <xs:complexType name="ArrayOfAddress"> <xs:sequence> <xs:element minOccurs="0" maxOccurs="unbounded" name="Address" nillable="true" type="Address" /> </xs:sequence> </xs:complexType> <xs:element name="Product" nillable="true" type="Product" /> <xs:complexType name="Product"> <xs:sequence> <xs:element minOccurs="0" maxOccurs="1" name="Name" type="xs:string" /> <xs:element minOccurs="0" maxOccurs="1" name="ProductCode" type="xs:string" /> <xs:element minOccurs="0" maxOccurs="1" name="Manufacturer" type="Manufacturer" /> <xs:element minOccurs="1" maxOccurs="1" name="DateIntroduced" type="xs:dateTime" /> <xs:element minOccurs="1" maxOccurs="1" name="UnitCost" type="xs:decimal" /> </xs:sequence> </xs:complexType> </xs:schema>
Like the XSD generated for an XML instance, a few assumptions are
made. For example, although you know from your previous usage that an
Address
element can only have up to three
Street
elements, the XSD does nothing to constrain
the number; it’s created a type called
ArrayOfString
, whose content is an unbounded
number of String
elements.
You can affect the generated XSD with
the judicious use of C# attributes. There are a number of attributes
that affect XSD generation, located in the
System.Xml.Serialization
namespace; a small subset
is listed in Table 8-3. Refer to the .NET
Framework SDK documentation section entitled
“Attributes That Control XML
Serialization” for the complete list.
Attribute name |
Purpose |
Properties |
XmlRootAttribute |
Identifies the class, structure, enumeration, or interface as the root element of an XML instance |
DataType ElementName IsNullable Namespace |
XmlElementAttribute |
Identifies the class, structure, enumeration, or interface as an element in an XML instance |
DataType ElementName Form IsNullable Namespace Type |
XmlAttributeAttribute |
Identifies the class, structure, enumeration, or interface as an attribute in an XML instance |
DataType AttributeName Form Namespace Type |
With this information, you can alter the
original source code to force the generated code to appear in a form
more to your liking. To take just the Product
type
from Product.cs, you can alter
xsd
’s output significantly by
marking some of its fields as attributes:
public class Product { [XmlAttributeAttribute(AttributeName="name")] public string Name; [XmlAttributeAttribute(AttributeName="productCode")] public string ProductCode; [XmlElementAttribute(IsNullable=false, ElementName="manufacturer")] public Manufacturer Manufacturer; [XmlAttributeAttribute(AttributeName="dateIntroduced")] public DateTime DateIntroduced; [XmlAttributeAttribute(AttributeName="unitCost")] public decimal UnitCost; }
The corresponding element in the generated schema0.xsd now looks like this:
<xs:element name="product" type="Product" /> <xs:complexType name="Product"> <xs:sequence> <xs:element minOccurs="0" maxOccurs="1" name="manufacturer" type="Manufacturer" /> </xs:sequence> <xs:attribute name="name" type="xs:string" /> <xs:attribute name="productCode" type="xs:string" /> <xs:attribute name="dateIntroduced" type="xs:dateTime" /> <xs:attribute name="unitCost" type="xs:decimal" /> </xs:complexType>
There’s much more to learn about serialization, and I’ll cover the topic in much more depth in Chapter 9.
3.14.70.203