Click here to Skip to main content
15,885,216 members
Articles / Programming Languages / XML
Article

XML Validation with XSD along with Custom Exception

Rate me:
Please Sign up or sign in to vote.
4.75/5 (4 votes)
2 Nov 2011CPOL2 min read 51.3K   21   5
Validating XML against defined XSD

Introduction

In this article, I will discuss about validating XML against defined XSD. Prior to getting into this article, it is mandatory that one should have basic knowledge on what is XML and XSD.

This article describes the below items:

  1. XML data validation with XSD like XML TAGS provided are present and appropriate with respect to XSD
  2. How to write custom validations like check to see email ID is valid or not
  3. How to generate XSD from XML
  4. How to generate Custom Error, when XML data validation fails
  5. How to write regular expression in XSD

Let's get into a sample with the below steps:

  • Step 1: Define XML
  • Step 2: Generate/Define XSD
  • Step 3: Write code to validate XML with XSD
  • Step 4: Handle Exception in by defining Custom Exception

Step 1: First define XML as follows & name XML file as Complex.XML

XML
<Person xmlns:ns0="http://Testing.Message">
  <Name>Surya Prakash</Name>
  <Address>Malkajgiri</Address>
  <Phone>9966537965</Phone>
  <Email>suryaprakasash.bg@gmail.com</Email>
</Person>

Step 2: How to generate XSD? Simply follow the below steps

  1. Open Complex.XML file -> Go to VS Menu -> XML -> Create Schema, this will generate XSD as below:
    XML
    <?xml version="1.0" encoding="utf-8"?>
    <xs:schema xmlns:ns0="http://Testing.Message" attributeFormDefault="unqualified" 
    	elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:element name="Person">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="Name" type="xs:string" />
            <xs:element name="Address" type="xs:string" />
            <xs:element name="Phone" type="xs:unsignedLong" />
            <xs:element name="Email" type="xs:string" />
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:schema>
  2. As we need to write code to check if Email ID is valid or not, we can do this by regular expression, by changing EMAIL tag type from String to Custom Type as follows:
    XML
    <xs:element name="Email" type="ValidateEmail" />
  3. As we have defined custom type, we need to define its structure as follows:
    XML
    <xs:simpleType name="ValidateEmail">
        <xs:restriction base="xs:string">
          <xs:pattern value="[A-Za-z0-9_]+([-+.'][A-Za-z0-9_]+)
    	*@[A-Za-z0-9_]+([-.][A-Za-z0-9_]+)*\.[A-Za-z0-9_]+([-.][A-Za-z0-9_]+)*" />
        </xs:restriction>
      </xs:simpleType>
  4. Finally our XSD file will be as:
    XML
    <?xml version="1.0" encoding="utf-8"?>
    <xs:schema xmlns:ns0="http://Testing.Message" attributeFormDefault="unqualified" 
    	elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:element name="Person">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="Name" type="xs:string" />
            <xs:element name="Address" type="xs:string" />
            <xs:element name="Phone" type="xs:string" />
            <xs:element name="Email" type="ValidateEmail" />
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:simpleType name="ValidateEmail">
        <xs:restriction base="xs:string">
          <xs:pattern value="[A-Za-z0-9_]+([-+.'][A-Za-z0-9_]+)
    	*@[A-Za-z0-9_]+([-.][A-Za-z0-9_]+)*\.[A-Za-z0-9_]+([-.][A-Za-z0-9_]+)*" />
        </xs:restriction>
      </xs:simpleType>
    </xs:schema>

Step 3: Create a new page as “Complex.aspx” and add a label to form by naming it as “lblMsg”

  1. Go to Complex.aspx.cs and define class level global variable as:
    C#
    private int nErrors = 0;
    private string strErrorMsg = string.Empty;
    public string Errors { get { return strErrorMsg; } }
  2. Go to Pageload event of Complex.aspx page:
    C#
    // IsValidXML return TRUE if no exception, false if any exceptions & 
    // respective message is appended to lblMsg
    // IsValidXML takes 2 parameters, param1: XML path, param2: XSD path
    
    if (!IsValidXml(@"D:\Surya Prakash\WorkAround\GopalSample\XML\Complex.xml", 
    	@"D:\Surya Prakash\WorkAround\GopalSample\XML\Complex.xsd"))
                lblMsg.Text =  Errors;
            else
                lblMsg.Text = string.Format("Success");
  3. IsValidXML function definition:
    C#
    public bool IsValidXml(string xmlPath, string xsdPath)
        {
            bool bStatus = false;
            try
            {
                // Declare local objects
                XmlReaderSettings rs = new XmlReaderSettings();
                rs.ValidationType = ValidationType.Schema;
                rs.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation | 
                XmlSchemaValidationFlags.ReportValidationWarnings;
                // Event Handler for handling exception & 
                // this will be called whenever any mismatch between XML & XSD
                rs.ValidationEventHandler += 
    		new ValidationEventHandler(ValidationEventHandler);
                rs.Schemas.Add(null, XmlReader.Create(xsdPath));
    
    
    		// reading xml
                using (XmlReader xmlValidatingReader = XmlReader.Create(xmlPath, rs))
                { while (xmlValidatingReader.Read()) { } }
    
                ////Exception if error.
                if (nErrors > 0) { throw new Exception(strErrorMsg); }
                else { bStatus = true; }//Success
            }
            catch (Exception error) { bStatus = false; }
    
            return bStatus;
        }
  4. EventHandler body definition for handling any exception:
    C#
    void ValidationEventHandler(object sender, ValidationEventArgs e)
        {
            if (e.Severity == XmlSeverityType.Warning) strErrorMsg += "WARNING: ";
            else strErrorMsg += "ERROR: ";
            nErrors++;
    
            if (e.Exception.Message.Contains("'Email' element is invalid"))
            {
                strErrorMsg = strErrorMsg + getErrorString
    		("Provided Email data is Invalid", "CAPIEMAIL007") + "\r\n";
            }
            if (e.Exception.Message.Contains
    		("The element 'Person' has invalid child element"))
            {
                strErrorMsg = strErrorMsg + getErrorString
    		("Provided XML contains invalid child element", 
    		"CAPINVALID005") + "\r\n";
            }
            else
            {
                strErrorMsg = strErrorMsg + e.Exception.Message + "\r\n";
            }
        }

Step 4: getErrorString: Custom error generation in XML string format

C#
string getErrorString(string erroString, string errorCode)
    {
        StringBuilder errXMl = new StringBuilder();
        errXMl.Append("<MyError> <errorString> ERROR_STRING </errorString> 	
			<errorCode> ERROR_CODE </errorCode> </MyError>");
        errXMl.Replace("ERROR_STRING", erroString);
        errXMl.Replace("ERROR_CODE", errorCode);
        return errXMl.ToString();
    }

Now save the application and run it with the below XML. You should be seeing SUCCESS message on the web page:

XML
<Person xmlns:ns0="http://Testing.Message">
  <Name>Surya Prakash</Name>
  <Address>Malkajgiri</Address>
  <Phone>9966537965</Phone>
  <Email>suryaprakasash.bg@gmail.com</Email>
</Person>

So far so good, let's modify the XML as follows:

  1. Add an extra tag, which is not defined in XSD. So run the application and look at the exception.

    Now the XML would look as:

    XML
    <Person xmlns:ns0="http://Testing.Message">
      <Name>Surya Prakash</Name>
      <Address>Malkajgiri</Address>
      <Phone>9966537965</Phone>
        <Email>suryaprakasash.bg@gmail.com</Email>
      <EmpId>123592</EmpId>
    </Person>
  2. Provide invalid email in EMAIL tag. So run the application and look at the exception.

    Now the XML would look as:

    XML
    <Person xmlns:ns0="http://Testing.Message">
      <Name>Surya Prakash</Name>
      <Address>Malkajgiri</Address>
      <Phone>9966537965</Phone>
      <Email>suryaprakasash.bg@gmail.@.com.com</Email>
    </Person>

Happy coding… hope this helps!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Comments and Discussions

 
QuestionThanks ! Pin
robotsys11-Oct-12 6:38
robotsys11-Oct-12 6:38 
AnswerRe: Thanks ! Pin
Bangla Gopal Surya Prakash12-Oct-12 5:36
Bangla Gopal Surya Prakash12-Oct-12 5:36 
GeneralVote 5 Pin
-=- Tino -=-25-Jun-12 2:41
-=- Tino -=-25-Jun-12 2:41 
GeneralMy vote of 5 Pin
Mauricio Leyzaola1-Mar-12 6:48
Mauricio Leyzaola1-Mar-12 6:48 
QuestionQuestion Pin
reminvestor15-Dec-11 10:51
reminvestor15-Dec-11 10:51 
I have a WCF service that is consuming XML messages from an application. I now you can create the XSD for required elements but I need validate that a required element value is passed. Do I need to write an expression attribute for all elements I need to validate or is there a better way to do this. I would like to generate the XSD separately as the XML changes during project development and then just add in the required value checks as easy as possible.

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

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