Recipe15.11.Validating Modified XML Documents Without Reloading


Recipe 15.11. Validating Modified XML Documents Without Reloading

Problem

You are using the XmlDocument to modify an XML document loaded in memory. Once the document has been modified, the modifications need to be verified and schema defaults need to be enforced.

Solution

Use the XmlDocument.Validate method to perform the validation and apply schema defaults and type information.

Create an XmlSchemaSet with the XML Schema document (book.xsd) and an XmlReader, and point the Schemas property of the XmlDocument to it:

 string xmlFile = @"..\..\Book.xml"; string xsdFile = @"..\..\Book.xsd"; // Create the schema set. XmlSchemaSet schemaSet = new XmlSchemaSet(); // Add the new schema with the target namespace // (could add all the schema at once here if there are multiple). schemaSet.Add("http://tempuri.org/Book.xsd", XmlReader.Create(xsdFile)); // Load up the XML file. XmlDocument xmlDoc = new XmlDocument(); // Add the schema. xmlDoc.Schemas = schemaSet; 

Load the book.xml file into the XmlDocument, set up a ValidationEventHandler to catch any errors, then call Validate with the event handler to validate book.xml against the book.xsd schema:

 // Validate after load. xmlDoc.Load(xmlFile); ValidationEventHandler eventHandler = ValidationEventHandler_15_11; xmlDoc.Validate(eventHandler); 

Add a new element node that is not in the schema into the XmlDocument and then call Validate again with the event handler to revalidate the changed XmlDocument. If the document triggers any validation events, then bValidXml is set to false by the ValidationEventHandler.

 // Set the initial check for validity to true at the class level. static bool bValidXml = true; // Add in a new node that is not in the schema. // Since we have already validated, no callbacks fire during the add… XmlNode newNode = xmlDoc.CreateElement("BogusElement"); newNode.InnerText = "Totally"; // Add the new element. xmlDoc.DocumentElement.AppendChild(newNode); // Now we will do validation of the new stuff we added. xmlDoc.Validate(eventHandler); if (bValidXml == true) {     Console.WriteLine("Successfully validated modified XML"); } else {     Console.WriteLine("Modified XML did not validate successfully"); } 

The ValidationEventHandler looks like the one from Recipe 15.4:

 private static void ValidationEventHandler_15_11(object sender,                             ValidationEventArgs e) {     // We got called so this isn't valid.     bValidXml = false;     Console.WriteLine("Validation Error Message: {0}", e.Message);     Console.WriteLine("Validation Error Severity: {0}", e.Severity);     if (e.Exception != null)     {         Console.WriteLine("Validation Error Line Number: {0}",                     e.Exception.LineNumber);         Console.WriteLine("Validation Error Line Position: {0}",                     e.Exception.LinePosition);         Console.WriteLine("Validation Error Source: {0}",                     e.Exception.Source);         Console.WriteLine("Validation Error Source Schema: {0}",                     e.Exception.SourceSchemaObject);         Console.WriteLine("Validation Error Source Uri: {0}",                     e.Exception.SourceUri);         Console.WriteLine("Validation Error thrown from: {0}",                     e.Exception.TargetSite);         Console.WriteLine("Validation Error callstack: {0}",                     e.Exception.StackTrace);     } } 

Discussion

There is an override to the XmlDocument.Validate method that allows you to pass a specific XmlNode to validate. If the XmlDocument is large, this override to Validate should be used:

 public void Validate(     ValidationEventHandler validationEventHandler,     XmlNode nodeToValidate ); 

One other approach to this problem is to instantiate an instance of the XmlNodeReader with the XmlDocument and then create an XmlReader with validation settings as shown in Recipe 15.4. This would allow for continual validation while the reader navigated through the underlying XML.

The output from running the code is listed here:

 Validation Error Message: The element 'Book' in namespace 'http://tempuri.org/Book. xsd' has invalid child element 'BogusElement'. List of possible elements expected: 'Chapter' in namespace 'http://tempuri.org/Book.xsd'. Validation Error Severity: Error Validation Error Line Number: 0 Validation Error Line Position: 0 Validation Error Source: Validation Error Source Schema: Validation Error Source Uri: file:///C:/PRJ32/Book_2_0/C%23Cookbook2/Code/ CSharpRecipes/Book.xml Validation Error thrown from: Validation Error callstack: Modified XML did not validate successfully 

Notice that the BogusElement element that you added was not part of the schema for the Book element so you got a validation error along with the information about where the error occurred. Finally, you got a report that the modified XML did not validate correctly.

See Also

See Recipe 15.4 and the "XmlDocument.Validate" topic in the MSDN documentation.



C# Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2004
Pages: 424

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net