Lets assume that the XML file that we wish to validate has details about orders. Each of the Order contains the Order ID, details about the Customer, Discount percent given and the details about Products. Following graphic(click for larger image) shows the XML file that we are using:
Orders.xml
To validate the XML shown above, we have the schema. The schema for the XML can be found here.
Validating XML using XmlValidatingReader:
To validate the XML file against a schema, we can use XmlValidatingReader. The steps involved are:- Create instance of XmlValidatingReader using the XML file to validate.
- Create an object of XmlSchema using the schema file to validate against.
- Hookup event for XmlValidatingReader.ValidationEventHandler.
- Read the Xml to the end using XmlValidatingReader.
using (XmlValidatingReader xmlValidatingReader = new XmlValidatingReader(new XmlTextReader("Orders.xml")))
{
// Create the schema object to validate XML files
XmlSchema xmlSchema = XmlSchema.Read(new XmlTextReader("Orders.xsd"), new ValidationEventHandler(Schema_ValidationError));
// Add to the collection of schemas for XmlValidatingReader
xmlValidatingReader.Schemas.Add(xmlSchema);
// Attach an event which will be filed on validating error
xmlValidatingReader.ValidationEventHandler += new ValidationEventHandler(xmlValidatingReader_ValidationEventHandler);
// Read the XML to the end
while (xmlValidatingReader.Read()) ;
Console.WriteLine("\nFinished validating XML file....");
}
Validating XML using XmlReaderSettings:
Validating XML using XmlReaderSettings follows almost the same path as that for XmlValidatingReader, with a difference that here we will be using XmlReaderSettings to pass in the schema details. Following are the steps to using XmlReaderSettings for validating an XML file:
- Create a XmlSchema object using the schema file.
- Create an object for XmlReaderSettings.
- Set the ValidationType of XmlReaderSettings as "Schema".
- Add the XmlSchema to the collection of schemas of XmlReaderSettings.
- Attach the event for XmlReaderSettings.ValidationEventHandler.
- Create an instance of XmlReader using XmlReader.Create() and passing in XML file to validate.
- Read the XmlFile to the end.
// Create the schema object
XmlSchema xmlSchema = XmlSchema.Read(new XmlTextReader("Orders.xsd"), new ValidationEventHandler(Schema_ValidationError));
// Create reader settings
XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
// Set validation type to schema
xmlReaderSettings.ValidationType = ValidationType.Schema;
// Add to the collection of schemas in readerSettings
xmlReaderSettings.Schemas.Add(xmlSchema);
// Attach event handler whic will be fired when validation error occurs
xmlReaderSettings.ValidationEventHandler += new ValidationEventHandler(xmlReaderSettings_ValidationEventHandler);
// Create object of XmlReader using XmlReaderSettings
using (XmlReader xmlReader = XmlReader.Create(new XmlTextReader("Orders.xml"), xmlReaderSettings))
{
// Read XML to the end
while (xmlReader.Read()) ;
Console.WriteLine("\nFinished validating XML file....");
}
The code behaves the same in both the cases. However, there is a small difference in how the exception message is displayed. Using theXmlValidatingReader tells about the element/attribute with incorrect value as per the data type, but using XmlReaderSetting provides a detailed error showing the incorrect value along with the expected datatype.
I hope I was able to provide most of you with a good insight on validating XML files using schemas. If you have been using some other method, please do share it here.
16 comments:
Great example! Do you know how we can do the validation for a bunch of XMLs against a set of schemas; instead of iterating over the schemas and adding them for validation? Hopefully I am clear in my question.
-Thanks
Chak Bireddy.
To validate multiple XML files against a set of schemas, you need to add all the schemas to the Schemas collection of XMLReaderSettings. However, XML files needs to be individyually validated. You can add the XmlReaders to list(one reader per file) and use the same XmlReaderSettings object in XMLReader.Create(). Loop over the list and read all XmlReaders to end. Thats it! Hope it was of help to you :)
If instead of [Orders](brackets used instead of curlies) someone gives an xml file that changes it to [Orders xmlns="abc"] the validation seems to fail with an error about abc:Orders element not declared.
Is there additional code that would allow validation of the XML for either situation when you don't know ahead of time which you are validating?
I am not very sure that I understood your question correctly. Can you please elaborate/provide an example?
Sorry for the confusion of my last post I didn't mean curlies.
I noticed if the Orders.xml file is changed and the first element is changed to < Orders xmlns="abc"> instead of just < Orders> the validation will fail. (Added spaces before the word Orders to allow this post).
Is there any simple way you know of to add a few more lines of code that would be able to validate the XML file no matter if the default namespace exists in the XML or not?
I may resort to string replacement and remove the default namespace but I was hoping there is a way to avoid that.
The XML file will be validated if you add the targetnamespace to your schema file(in your case, "abc"). If you wish to do without it, you might have to resort to string manipulation as you said.
Please help out in following code snippet, please reply me at hvyas@irevna.com:
For the first time it gives prompt while XmlSchema.Read(). Second time schema_collection_object is not null and so does not enter into this block of code.
Please help............
private static XmlSchemaCollection schema_collection_object;
private static XmlSchema m_ifschema;
-------
-------
-------
if (schema_collection_object==null)
{
schema_collection_object=new XmlSchemaCollection();
XmlTextReader xmlFile=new XmlTextReader(path);
//path contains the path of the .xsd file
m_ifschema=XmlSchema.Read(xmlFile,new ValidationEventHandler(ValidationCallBack));
//*******error is genarated in the above statement
m_ifSchema.Compile(newValidationEventHandler(Valid ationCallBack));
schema_collection_object.Add(m_ifSchema);
}
suppose I added new tag or attribute to xml file then will it work ?
it should show the error because this tag or attribute is not there in schema
Yes! Adding a new element/node will result in an error. Let's say, I add a new node by name "Date" in the Orders.xml, I'll get an error saying "The element 'Orders' has invalid child element 'Date'. List of possible elements
expected: 'Order'."
ok but do we need to have two event handlers?
like...
Schema_ValidationError
and
xmlReaderSettings_ValidationEventHandler
???
thanks
The element 'Orders' has invalid child element 'Date'. List of possible elements
expected: 'Order'."
I can see this error in my Xml where i added new node but if I write this validation code to my button click event this it doesn't show any errors
@anonymous,
You need to subscribe to xmlReaderSettings.ValidationEventHandler apart from one in XMLSchema constructor. I think it should work.
Great example.
Is there a way to validate files that have been sent with incorrect namespace declarations.
What if you dont have the xml schema. I just want to validate only xml document i.e., creating xml schema on fly. Is it possible to create on fly the xml schema.
@Anonymous,
You can generate schema from the Xml file but that won't be correct way to validate your Xml. Since you'll be using an XML file to generate schema, Xml will always be validated against it. i.e. validation will never fail. Are you sure you want to do this only?
Post a Comment