Click here to Skip to main content
15,892,059 members
Articles / Programming Languages / C#
Article

XML Validation Patterns in .NET 2.0 using C#

Rate me:
Please Sign up or sign in to vote.
2.19/5 (10 votes)
28 Feb 2006CPOL2 min read 96.8K   23   13
This article highlights some ways to validate inbound XML documents .NET 2.0 using the C# programming language. It also addresses some changes to the general pattern from .NET 1.1

Introduction

If anyone does not know this, here is a quick code snippet that shows one way to validate an XML document.

C#
FileStream fs = File.Open("../../signatureinstance.xml", FileMode.Open);
XmlTextReader reader = new XmlTextReader(fs);
XmlValidatingReader xvr = new XmlValidatingReader(reader);
xvr.ValidationType = ValidationType.Schema;
xvr.Schemas.Add(null, "../../signatureschema.xsd");
xvr.ValidationEventHandler += new ValidationEventHandler(xvr_ValidationEventHandler);
XmlDocument xdoc = new XmlDocument();
xdoc.Load(xvr);

In the above example, the XML instance to be validated is signatureinstance.xml.  The schema doing the validation is signature.xsd.  A type called XmlValidatingReader, found in the System.Xml namespace, is used to perform the validation at load time.  (It is also possible to load the XmlDocument first and use the Validate() function to validate the contents against a given schema.

Just in case anyone reading does not understand how I might have gotten to this point, I will go through a few steps (using the Visual Studio .NET 2005 IDE).

The first step (after creating a project of course) is adding a schema to your project.  The XML schema template should be listed amongst other document types that can be added. Make sure not to select Dataset; although they both use .xsd extensions and are essentially the same technology, there are some differences. The item we are looking for is shown in the picture below:

addschematoproject.jpg

Next we design the schema using the toolbox, which at this point should have changed to a list of tools related to editing XML schemas. The new toolbox view is illustrated in the picture below:

schematoolbox.jpg

Now we can design our schema. The Signature schema design is given below:

schema.jpg

Once that's done, we can work on creating a sample instance using the schema as a reference. VS.NET 2005 allows you to associate a given schema to the instance you are currently working with. The schema property can be found on the property pane. 

associateschema.jpg

When you click on the ellipsis for the schema property, a property page with all the currently known schemas will appear:

schemaselector.jpg

You can use this tool to add more known schemas. For this project, select the signature schema designed.

Using this, I created the schema shown below:

XML
<?xml version="1.0" encoding="utf-8" ?>
<Signature xmlns="http://tempuri.org/XMLSchema1.xsd">
<Company>
Perficient Inc.
</Company>
<Name>Jerod Edward Moemeka</Name>
<Position>Architect</Position>
<OfficeAddress>
<Address>622 Emerson Road</Address>
<Suite>400</Suite>
<City>St. Louis</City>
<State>MO</State>
<Zip>63141</Zip>
</OfficeAddress>
<ContactInfo>
<EmailAddress>jerod.moemeka@perficient.com</EmailAddress>
<CompanyURL>www.perficient.com</CompanyURL>
<PhoneInfo>
<OfficePhoneNumber>1234567890</OfficePhoneNumber>
<MobileNumber>9876543210</MobileNumber>
<FaxNumber>1112223333</FaxNumber>
</PhoneInfo>
</ContactInfo>
</Signature>

At this point, validation using the example above will work.  However, there are also some other ways to accomplish this. If for instance, you did not mind the document being loaded ahead of time and then validated, you could use the DOM object directly to validate as follows:

C#
XmlDocument xdoc = new XmlDocument();
xdoc.Load("../../signatureschemainstance.xml");
xdoc.Schemas.Add(null, "../../signatureschemaschema.xsd");
ValidationEventHandler veh = new ValidationEventHandler(xvr_ValidationEventHandler);
xdoc.Validate(veh);

In .NET 2.0, the XmlValidatingReader is deprecated, hence the initial example should be as follows:

C#
//load instance into memory
FileStream fs = File.Open("../../signatureinstance.xml", FileMode.Open);
XmlDocument xdoc = new XmlDocument();
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add(null, "../../signatureschema.xsd");

//add resolver to pass security if accessing web site to receive schema
XmlUrlResolver resolver = new XmlUrlResolver();
resolver.Credentials = System.Net.CredentialCache.DefaultCredentials;
settings.XmlResolver = resolver;

//this line is necessary for validation to work
settings.ValidationType = ValidationType.Schema;
settings.ValidationEventHandler +=
	new ValidationEventHandler(xvr_ValidationEventHandler);
XmlReader reader = XmlReader.Create(fs, settings);
xdoc.Load(reader);
fs.Close();

To load the schema once and not continually, go get it from the source URL (in this case ../../signatureschema.xsd. We can rewrite this to use the Schema object as follows:

C#
ValidationEventHandler veh = new ValidationEventHandler(xvr_ValidationEventHandler);
XmlSchema schema = XmlSchema.Read(new XmlTextReader("../../productschema.xsd"), veh);

FileStream fs = File.Open("../../productcataloginstance.xml", FileMode.Open);
XmlDocument xdoc = new XmlDocument();
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add(schema);
//this line is necessary for validation to work
settings.ValidationType = ValidationType.Schema;
settings.ValidationEventHandler +=
	new ValidationEventHandler(xvr_ValidationEventHandler);
XmlReader reader = XmlReader.Create("../../productcataloginstance.xml", settings);
xdoc.Load(reader);

History

  • 28th February, 2006: Initial post

License

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


Written By
United States United States
Hi I'm Edward Moemeka,
For more interesting articles about stuff check out my blog at http://moemeka.blogspot.com
To correspond, email me at edward.moemeka@synertry.com
To support my company, thus help me feed my family, check out our awesome online preview at www.synertry.com. Remember, its in alpha Wink | ;-)

Comments and Discussions

 
GeneralI am unable to make link between XSD and XML Pin
chirag_pandey13-Jun-09 2:27
chirag_pandey13-Jun-09 2:27 
GeneralRe: I am unable to make link between XSD and XML Pin
Edward Moemeka17-Jun-09 16:43
Edward Moemeka17-Jun-09 16:43 
QuestionXML Validation problem Pin
Gorets3-Jan-08 4:08
Gorets3-Jan-08 4:08 
GeneralRe: XML Validation problem Pin
Gorets3-Jan-08 4:13
Gorets3-Jan-08 4:13 
GeneralXmlValidatingReader is obsolete Pin
Thuc.Nguyen22-Jun-07 0:07
professionalThuc.Nguyen22-Jun-07 0:07 
GeneralRe: XmlValidatingReader is obsolete Pin
AndyCLon21-May-08 4:30
AndyCLon21-May-08 4:30 
QuestionWhy not simplier? Pin
Arjunachan30-May-06 0:31
Arjunachan30-May-06 0:31 
AnswerRe: Why not simplier? Pin
abnorm25-Jul-06 21:32
abnorm25-Jul-06 21:32 
AnswerHere's a more efficient way to do this.... Pin
DaveBlack2-Apr-07 10:14
DaveBlack2-Apr-07 10:14 
IMHO, if you're going to provide an example, you might as well show the method which uses "best practices". Using XmlDocument and loading the entire DOM when you only need to validate the XML is very inefficient. In addition, your example doesn't wrap the creation of the XmlReader instance in a "using" block, nor does it explicitly call Close() on the XmlReader - two bad practices. A correct implementation using "best practices" follows:

//Consider making the XmlReaderSettings instance static if it uses the same settings
//for all xml validation
XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
xmlReaderSettings.CheckCharacters = true;
xmlReaderSettings.CloseInput = true;

//if you have a finite number of schemas, consider caching each schema in
//a static XmlSchemaSet instance 
xmlReaderSettings.Schemas.Add( null, uriOfSchema );
xmlReaderSettings.ValidationType = ValidationType.Schema;
xmlReaderSettings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
...add any other ValidationFlags necessary here...

//Note that the use of a delegate here is not necessary and you can just as
//easily wire your event handler as a separate static method
xmlReaderSettings.ValidationEventHandler += delegate( object sender, ValidationEventArgs args )
{
    string errorMessage = string.Format( 
           "Xml validation failed against schema: '{0}', Message: {1}, Severity: {2}, Exception: {3}", uriOfSchema, args.Message, args.Severity, args.Exception );
    System.Diagnostics.Trace.WriteLine( errorMessage );

    //Perform any error handling necessary
};

try
{
    //Wrap the creation of the XmlReader in a 'using' block since
    //it implements IDisposable
    using( XmlReader xmlReader = XmlReader.Create( xmlToValidate, xmlReaderSettings ) )
    {
        if ( xmlReader != null )
        {
            while ( xmlReader.Read() )
            {
                //empty loop - if Read fails it will raise an error via the 
                //ValidationEventHandler wired to the XmlReaderSettings object
            }
            
            //explicitly call Close on the XmlReader to reduce strain on the GC
            xmlReader.Close();
        }
    }
}
catch( ..various types of Exceptions can be thrown by the XmlReader.Create() method)
{
    //do any exception handling here...
}
finally
{
    //do any other ExceptionHandling here...
    //NOTE: the XmlReader created earlier is Disposed of automatically by
    //placing it inside a 'using' block - so there is no need to do anything
    //with it here.  The 'using' block will also clean
    //it up even if there is an Exception thrown in the 'using' block
}



You can certainly say that my example is much more code to write, and it is, but I *guarantee* it is far faster and more efficient : )

DaveBlack, MCP
GeneralRe: Here's a more efficient way to do this.... Pin
c00ks17-Oct-07 4:04
c00ks17-Oct-07 4:04 
GeneralRe: Here's a more efficient way to do this.... Pin
mats kristiansson27-Mar-11 1:11
mats kristiansson27-Mar-11 1:11 
GeneralRe: Here's a more efficient way to do this.... Pin
DaveBlack27-Mar-11 6:26
DaveBlack27-Mar-11 6:26 
AnswerRe: Why not simplier? Pin
valamas21-Oct-07 15:37
valamas21-Oct-07 15:37 

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.