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

Simplifying Serialization and De-serialization Processes With XSD.EXE

By , 30 Jan 2006
 

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

About the Author

Y.M.Gopala Krishna Reddy alias Murali
Web Developer
United States United States
Member
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.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Questiona string can't be longer than 30chars, what sould I do?membertapgyn31 Aug '09 - 10:27 
I have an XSD file named Person,
and Person has EmailAddress,
this string shouldn't be longer than 30 characters,
and it should be a valid email, so my XSD contains a RegEx for it.
 
will it somehow generate this in code, say, in the Getters and Setters?
 

please somebody answer, this is a really important thing from work :(
GeneralUnable to find a version of the runtime to run this applicationmembertuxolino29 Jun '07 - 0:28 
hi, .. this is the message error i've been seen when I try to run xsd.exe" ...
 
Can U suggest me a solution to this problem ???
 
Thanks a lot...
 
TuXolino
GeneralRe: Unable to find a version of the runtime to run this applicationmemberY.M.Gopala Krishna Reddy alias Murali31 Jul '07 - 2: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]memberPingu2217 May '07 - 4:30 
Hi. When I create my xsd with xsd.exe some fields have the [System.Xml.Serialization.XmlIgnoreAttribute()] before and the application automatically creates a public bool <fieldName>Specified; after that line.
How can I avoid the xsd.exe to do this so all fields stay serializable without having to put that <fieldName>Specified = True?
 
Thanks.
 

-- modified at 10:44 Thursday 17th May, 2007
GeneralRe: XmlIgnoreAttributememberY.M.Gopala Krishna Reddy alias Murali31 Jul '07 - 2:31 
If you specify a field as optional in the schema. In that case it generates a boolean variable (Specified = True ) for each optional fields. While deserializing if the optional field is not present in the XML then the corresponding boolean field (Specified) in the created object will have a value "False". so before using the variable you have check its corresponding boolean( that indicates whether the element was provides in the xml).
 
The only way to avoid generating boolean variable is not to specify the optional fields in the schema.
 
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.

GeneralPopulating the class with XML datamemberPandiani22 Jan '07 - 11:34 
Hi there,
Can u please explain how you populate the various classes with data?
 
What I need is to either create an XML file based on the data properties to send to the web-service and to retreive the XML output from the web service and populate the output classes from an XML reader containing the return values (input / output)
 
What is the best way?
 
Thanks,
Filippo
GeneralRe: Populating the class with XML datamemberY.M.Gopala Krishna Reddy alias Murali31 Jul '07 - 2:36 
If you want to send xml to a webservice, first you serialize the you object into xml, send this xml in the form of string ( webmethods with parameter string). Once the method returns deserialize the response into the required object.
 
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.

QuestionIsn't this a lot of work?memberJim Crafton31 Jan '06 - 4:00 
It would be nice if you'd clarify in the article why you seem to be jumping through so many hoops. I'm not very familiar with XSD or whatever it's called, but what you've presented seems like a LOT of extra work to just serialize (or de-serialize) some arbitrary data. What else does this achieve by going this route?
 
¡El diablo está en mis pantalones! ¡Mire, mire!
 
Real Mentats use only 100% pure, unfooled around with Sapho Juice(tm)!
 
SELECT * FROM User WHERE Clue > 0
0 rows returned

Save an Orange - Use the VCF!
AnswerRe: Isn't this a lot of work?memberBoneSoft13 Dec '06 - 7:25 
I've found that most situation that warrent XML serialization are when you have and XSD or XML in a specific format that you need to work with programatically. Or if you have a model that represents information like configuration information that you want to serialize to an XML config file. But still this does seem like the hard way to use it. And XSD.exe is not the best solution for generating code from XML or XSD. I prefer working with a tool like Skeleton Crew[^]. Then there is very little work you have to do the turn XML into object or visa-versa.
 


Try code model generation tools at BoneSoft.com.

QuestionYou're the famous bowler, right?membergxdata30 Jan '06 - 19:43 
Those in N America won't get this, of course

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

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