Friday, May 27, 2011

Deserialzing XML With Validation

Many of the times we come across situations we have an XML file as input from the customer.
We need to:
1. Validate the XML against a known schema
2. Deserialize it into a known object

1. To validate the XML against a known schema, we should either have a pre-existing schema, which has been already provided to you, or you have to create a schema based on the sample XML file. Be careful, that your XML file will cover all the cases against which the schema has to be evaluated.
Example of creating a schema by the xml file using XSD Tool:
At the VS command prompt type: -->xsd AdhocTestCases.xml
The above command generates an ouput xml schema as AdhocTestCases.xsd which you can use for validation of the user XML.

2. Create a known .NET object that you can use to in the application to manipulate the XML file a shown:
xsd AdhocTestCases.xml
xsd AdhocTestCases.xsd /c
The above command generates an AdhocTestCases.cs class [use /c /l:vb for vb class file] for the corresponding schema. All the schema elements would be mapped to properties in the resultant class.

The Actual conversion
1. Loading the Schema to a stream
If you have a schema available at the output directory or at some other location, you can obtain the stream for that particular xsd using any of the IO classes (For example, FileStream).
Stream stream = File.OplenRead(locationOfTheFile);

If you have the schema as an embedded resource in the assembly
// Build Action = Embedded Resource
// Copy To Output Directory = Do not Copy
XmlSchemaSet schema = new XmlSchemaSet();
Stream stream= Assembly.GetExecutingAssembly().GetManifestResourceStream("XmlReport.ReportSchmea.xsd");


2. Create a reader settings specifying the type of
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add(null, XmlReader.Create(stream));
settings.ValidationType = ValidationType.Schema;
settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);

3. Open the XML and specify the settings which contain the schema
XmlReader reader = XmlReader.Create("AdhocTestCases.xml", settings);

4. Try to desrerialize the type into the object of type xsd
XmlSerializer serialize = new XmlSerializer(typeof(ReportTestDefinition));
definition= (ReportTestDefinition)serialize.Deserialize(reader);

5. Implement ValidationEventHanlder
You can optionally implement the ValidationEventHandler on the XmlReaderSettings class to specifying some clean up if required or posting the error information.

private static void ValidationCallBack (object sender, ValidationEventArgs args) {
if (args.Severity==XmlSeverityType.Warning)
Console.WriteLine("\tWarning: Matching schema not found. No validation occurred." + args.Message);
else
Console.WriteLine("\tValidation error: " + args.Message);
}

No comments: