Click here to Skip to main content
Click here to Skip to main content

Simplifying Serialization and De-serialization Processes With XSD.EXE

, 30 Jan 2006
Rate this:
Please Sign up or sign in to vote.
XSD.EXE is an XML Schema Definition tool that generates XML schema or common language runtime classes from XDR, XML, and XSD files, or from classes in a runtime assembly.

Introduction

XSD.EXE is an XML Schema Definition tool that generates XML schema or common language runtime classes from XDR, XML, and XSD files, or from classes in a runtime assembly.

An XML-schema is a document that describes the valid format of an XML data-set. This definition includes what elements are (and are not) allowed at any point, what the attributes for any element may be, the number of occurrences of elements, etc.

Deserialization Process

Let us assume you are building a web service, which takes XML (in the form of string) as input, and shown below is the schema of the data that is to be exchanged between the clients and your web service.

<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:complexType name="EmployeeType">
       <xsd:sequence>
        <xsd:element name="EmployeerID" type="xsd:int" />
        <xsd:element name="Name" type="NameType" />
        <xsd:element name="SSN" 
                   type="xsd:string" minOccurs="0" />
        <xsd:element name="CurrentAddress" 
                   type="AddressType" />
        <xsd:element name="PreviousAddress" 
                   type="AddressType" 
                   minOccurs="0" maxOccurs="2" />
        <xsd:element name="DriverLicense" 
                   type="xsd:string" minOccurs="0" />
        <xsd:element name="Phone" 
                   type="PhoneType" 
                   minOccurs="0" maxOccurs="3" />
        <xsd:element name="DOB" 
                   type="xsd:string" minOccurs="0" />
        <xsd:element name="YOB" 
                   type="xsd:string" minOccurs="0" />
       </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="NameType">
        <xsd:annotation>
            <xsd:documentation />
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="Surname" 
                   type="xsd:string"></xsd:element>
            <xsd:element name="First" 
                   type="xsd:string"></xsd:element>
            <xsd:element name="Middle" minOccurs="0" 
                   type="xsd:string"></xsd:element>
            <xsd:element name="Gen" minOccurs="0" 
                   type="xsd:string"></xsd:element>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="AddressType">
        <xsd:sequence>
            <xsd:element name="StreetNumber" minOccurs="0" 
                   type="xsd:int"></xsd:element>
            <xsd:element name="StreetName" 
                   type="xsd:string"></xsd:element>
            <xsd:element name="City" 
                   type="xsd:string"></xsd:element>
            <xsd:element name="State" 
                   type="xsd:string"></xsd:element>
            <xsd:element name="Zip" 
                   type="xsd:string"></xsd:element>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="PhoneType">
        <xsd:sequence>
            <xsd:element name="Type" minOccurs="0" 
                   type="xsd:string"></xsd:element>
            <xsd:element name="Number" type="xsd:string" />
        </xsd:sequence>
    </xsd:complexType>
    <xsd:element name="EmpType" 
                   type="EmployeeType"></xsd:element>
</xsd:schema>

To deserialize, first we need to build a class as below:

[System.Xml.Serialization.XmlRootAttribute("EmpType", 
            Namespace="", IsNullable=false)]
public class EmployeeType 
{
  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public int EmployeerID;

  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public NameType Name;
    . . . . . .
    . . . . . .
    . . . . . .
}

public class NameType 
{
  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public string Surname;
     . . . . . .
     . . . . . .
     . . . . . .
}
public class PhoneType 
{
  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public string Type;
  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public string Number;
}

public class AddressType 
{
  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public int StreetNumber;
    . . . . . .
    . . . . . .
    . . . . . .
}

Building such a class by seeing the XML schema is a time consuming and error prone process. An alternate approach is to use XSD.EXE.

First, build the class using the XSD.EXE tool provided by the .NET framework.

///////////Syntax of xsd.exe/////////
XSD.EXE file.xsd /classes /language:[language]

The output class is as follows:

using System.Xml.Serialization;

[System.Xml.Serialization.XmlRootAttribute(
  "EmpType", Namespace="", IsNullable=false)]
public class EmployeeType
{
  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public int EmployeerID;

  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public NameType Name;

  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public string SSN;
  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public AddressType CurrentAddress;

  [System.Xml.Serialization.XmlElementAttribute("PreviousAddress",
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public AddressType[] PreviousAddress;
  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public string DriverLicense;

  [System.Xml.Serialization.XmlElementAttribute("Phone",
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public PhoneType[] Phone;
  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public string DOB;
  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public string YOB;
}

public class NameType
{
  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public string Surname;
  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public string First;
  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public string Middle;
  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public string Gen;
}

public class PhoneType
{
  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public string Type;
  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public string Number;
}

public class AddressType
{
  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public int StreetNumber;

  [System.Xml.Serialization.XmlIgnoreAttribute()]
  public bool StreetNumberSpecified;
  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public string StreetName;
  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public string City;

  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public string State;

  [System.Xml.Serialization.XmlElementAttribute(
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public string Zip;
}

If you see the file generated by the XSD.EXE tool, it has added a boolean variable StreetNumberSpecified, which indicates whether the StreetNumber element was supplied in the input or not. So whenever we are about to use the StreetNumber, first we need to check StreetNumberSpecified, and if it is true then we can use the StreetNumber variable. Similarly, it has added a boolean variables for other elements whose minOccurs="0 and whose data type is int. If the data type is string then it will not add the boolean variable that corresponds to the string variable.

Now, add this class to your web service. Then, change the deserialization process as follows:

public string ProcessRequest (string strEMPDet)
{
    try
    {
        string strEMPDet = 
          ConfigurationSettings.AppSettings.Get("XSDPath");
        XmlValidatingReader vr = new 
          XmlValidatingReader(strEMPDet, XmlNodeType.Element);
        vr.ValidationType = ValidationType.Schema;
        vr.Schemas.Add( “”, strXSDFilePath );
        while( vr.Read() )
        {
        }
    }
    catch( XMLException ex )
    {
        //log exception
    }
}

The validating reader class is inherited from an XML reader. The validating reader examines and validates each single piece of XML according to the requested validation type. The XmlValidatingReader class does not explicitly provide a single method good at validating the whole content of a document, instead it validates reader works incrementally, node by node, as the underlying reader proceeds. If just write a try catch block we can’t track all the validation errors, i.e., we can't trap all the nodes that are not following the schema. In order to track messages and detects errors (all nodes), the application must define an event handler. If a validating reader happens to work on a badly-formed XML document, no event is fired but an XmlException exception is raised.

The handler for the event has the following signature:

public delegate void ValidationEventHandler(object sender, 
                     ValidationEventArgs e);

The complete code is:

StringBuilder alValidationErrors =new StringBuilder();
[WebMethod]
public bool ProcessRequest(string strEMPDet)
{
    EmployeeType objEmp=new EmployeeType();
    try
    {
        string strXSDFile = 
          ConfigurationSettings.AppSettings.Get("XSDPath" );;
        string strRequestXSDNameSpace="";
        //Read in the input XML in a TextReader...
        TextReader tr = (TextReader)new StringReader(strEMPDet);
    
        //Create a validating XML reader and validate...
        XmlParserContext context = new XmlParserContext(null, 
                                   null, "", XmlSpace.None );
        XmlValidatingReader vr = new 
          XmlValidatingReader(strEMPDet, 
          XmlNodeType.Element, context );
        vr.ValidationType = ValidationType.Schema;
        vr.Schemas.Add( strRequestXSDNameSpace, strXSDFile );
        vr.ValidationEventHandler += new 
          ValidationEventHandler(this.ValidationEventHandle );
        while( vr.Read() ){}
        //Now deserialize.
        objEmp = ( EmployeeType ) ( new XmlSerializer( 
                   typeof( EmployeeType ) ) ).Deserialize( tr );
    }
    catch( Exception ex)
    {
        //logging
        return false;
    }
    return true;
}

private void ValidationEventHandle (object sender, ValidationEventArgs args)
{
    alValidationErrors.Append(args.Message + Environment.NewLine);
}

With this approach, we can find out the list of all nodes that are not following the XSD.

The advantages of this approach are:

  1. Building the class to hold the incoming data is easy.
  2. Whenever there is a change in schema, we need to update the file.xsd alone, no need to change the deserialization process and rebuild the application.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Y.M.Gopala Krishna Reddy alias Murali
Web Developer
United States United States
Mr.Y.M.Gopala Krishna Reddy is working as Associate in a leading MNC.His area's of intrest are ReverseEngineering,WebServices and Developing applications using DotNet.

Comments and Discussions

 
GeneralMessage Automatically Removed PinmemberDavid Harrison26-Aug-14 1:51 
Questiona string can't be longer than 30chars, what sould I do? Pinmembertapgyn31-Aug-09 11:27 
GeneralUnable to find a version of the runtime to run this application Pinmembertuxolino29-Jun-07 1:28 
GeneralRe: Unable to find a version of the runtime to run this application PinmemberY.M.Gopala Krishna Reddy alias Murali31-Jul-07 3:23 
I think you have not installed visual studio dotnet. XSD is a seperate tool that you can execute at visualstudio command prompt PStart->All Programs--> Visual studio dotnet-->Visual studio .net tools-->
 
Mr.Y.M.Gopala Krishna Reddy is working as Associate in a leading MNC.His area's of intrest are ReverseEngineering,WebServices and Developing applications using DotNet.applications using DotNet.

GeneralXmlIgnoreAttribute [modified] PinmemberPingu2217-May-07 5:30 
GeneralRe: XmlIgnoreAttribute PinmemberY.M.Gopala Krishna Reddy alias Murali31-Jul-07 3:31 
GeneralPopulating the class with XML data PinmemberPandiani22-Jan-07 12:34 
GeneralRe: Populating the class with XML data PinmemberY.M.Gopala Krishna Reddy alias Murali31-Jul-07 3:36 
QuestionIsn't this a lot of work? PinmemberJim Crafton31-Jan-06 5:00 
AnswerRe: Isn't this a lot of work? PinmemberBoneSoft13-Dec-06 8:25 
QuestionYou're the famous bowler, right? Pinmembergxdata30-Jan-06 20:43 
AnswerRe: You're the famous bowler, right? PinmemberY.M.Gopala Krishna Reddy alias Murali31-Jan-06 19:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.1411022.1 | Last Updated 30 Jan 2006
Article Copyright 2006 by Y.M.Gopala Krishna Reddy alias Murali
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid