XML SchemaValidator

This article shows how to validate an XML document against a schema using C#. For demonstration of this, I have created a GUI application using Visual Studio 2005 Express Edition.


Introduction: This article shows how to validate an XML document against a schema using C#. For demonstration of this, I have created a GUI application using Visual Studio 2005 Express Edition.

XML is a tag-based markup language used mainly for data transfer. The main advantage of XML is that it is extensible. It allows user-defined tags to store data. Also since it is written purely as text, it is portable across various software and hardware platforms.

A well-formed XML document follows certain rules. The rules for well-formed XML documents are as follows:

  1. Every tag must have a corresponding closing tag.
  2. Empty tags must be terminated with a slash (/).
  3. Attribute values must be enclosed within quotes.
  4. Opening and closing tags must be written using the same case.
  5. Tags must be nested and not overlapping.

The structure of an XML file can be specified by creating a schema. A schema is used to validate the structure and data of an XML file. If an XML file conforms to its schema, it is considered to be valid.

Microsoft has created a language called XML Schema Definition (XSD) to help in validating an XML file against a schema. The syntax of XSD is similar to XML.

A schema-validator can be created to validate an XML file against a schema.

Assume the following XML document:

<?xml version="1.0" encoding="UTF-8"?>
<employees>
<emp id="S001">
<name>ABC</name>
<salary>5000
</emp>
<emp id="S002">
<name>PQR</name>
<salary>-7000</salary>
</emp>
<emp id="S003">
<name>XYZ</name>
<salary>9000</salary>
</emp>
</employees>

Assume the following (Schema) XSD document:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="employees" type="empdt"/>
<xsd:complexType name="empdt">
<xsd:sequence>
<xsd:element name="emp" type="edt" minOccurs="1" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="edt">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="salary" type="xsd:positiveInteger"/>
</xsd:sequence>
<xsd:attribute name="id" type="idtype"/>
</xsd:complexType>
<xsd:simpleType name="idtype">
<xsd:restriction base="xsd:string">
<xsd:pattern value="S\d{3}"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>

The following code is used to browse for the XML file and display the XML filename in the text box:

        private void btnBrowseXML_Click(object sender, EventArgs e)
        {
            try
            {
                FileDialog dialog = new OpenFileDialog();
                dialog.Filter = "XML Files (*.xml)|*.xml|All Files (*.*)|*.*";
                dialog.FilterIndex = 1;
                dialog.DefaultExt = "xml";
                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    txtXMLFileName.Text = dialog.FileName;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

The following code is used to browse for the XSD file and display the XSD filename in the text box:

        private void btnBrowseXSD_Click(object sender, EventArgs e)
        {
            try
            {
                FileDialog dialog = new OpenFileDialog();
                dialog.Filter = "Schema Files (*.xsd)|*.xsd|All Files (*.*)|*.*";
                dialog.FilterIndex = 1;
                dialog.DefaultExt = "xsd";
                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    txtXSDFileName.Text = dialog.FileName;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

The following code is used to validate the XML file against the Schema:

        private void btnValidate_Click(object sender, EventArgs e)
        {
            try
            {
                XmlReader reader = XmlReader.Create(txtXMLFileName.Text);
                XmlValidatingReader vreader = new XmlValidatingReader(reader);
                XmlReader schemareader = XmlReader.Create(txtXSDFileName.Text);
                XmlSchemaCollection schemacollection = new XmlSchemaCollection();
                schemacollection.Add("", txtXSDFileName.Text);
                vreader.Schemas.Add(schemacollection);
                vreader.ValidationEventHandler += new ValidationEventHandler(vreader_ValidationEventHandler);
                while (vreader.Read()) { }
                if (!error_flag)
                {
                    MessageBox.Show("No Error", "Valid XML file", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        void vreader_ValidationEventHandler(object sender, ValidationEventArgs e)
        {
            MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            error_flag = true;
        }
    }

The XmlReader class is used to open the XML file and the XSD file. The XmlValidatingReader class is used to create a validating reader. The Add() method of the XmlSchemaCollection adds namespaces to the schema collection. The Add() method of the XmlValidatingReader class adds the schema collection to the validating reader. The ValidationEventHandler event of the validating reader is used to handle all schema validation errors. Finally the Read() method of the validating reader is used to read the XML file and report any errors. If any validation errors occur, the ValidationEventHandler is called to handle the error and display the error message.

Any errors because of the XML file not being well-formed are handled by the try-catch exception handler. The class level variable 'error_flag ' is used to check if validation error occurred or not.

The following namespaces must be added for the XML related classes:

  1. System.Xml

  2. System.Xml.Schema

Following is the output screen, if the XML document is not well-formed:

XML1.gif

The following output screen will be displayed if the XML document is not valid as per its schema:

XML2.gif

Finally, if all errors are removed and the XML file is well-formed as well as valid, the following screen is displayed:

XML3.gif