I’m currently working on an XML File Explorer application, which I intend on highlighting XML files which do not conform to an XSD schema, as part of this I have created a class for containing the details of performing XSD validation against an XML document, which I thought I would share with you (although the XML File Explorer will be open source).
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Xml; using System.Xml.Schema; namespace KetoLibrary.Xml { public class XsdValidator { public List<XmlSchema> Schemas { get; set; } public List<String> Errors { get; set; } public List<String> Warnings { get; set; } public XsdValidator() { Schemas = new List<XmlSchema>(); } /// <summary> /// Add a schema to be used during the validation of the XML document /// </summary> /// <param name="schemaFileLocation">The file path for the XSD schema file to be added for validation</param> /// <returns>True if the schema file was successfully loaded, else false (if false, view Errors/Warnings for reason why)</returns> public bool AddSchema(string schemaFileLocation) { if (String.IsNullOrEmpty(schemaFileLocation)) return false; if (!File.Exists(schemaFileLocation)) return false; // Reset the Error/Warning collections Errors = new List<string>(); Warnings = new List<string>(); XmlSchema schema; using (var fs = File.OpenRead(schemaFileLocation)) { schema = XmlSchema.Read(fs, ValidationEventHandler); } var isValid = !Errors.Any() && !Warnings.Any(); if (isValid) { Schemas.Add(schema); } return isValid; } /// <summary> /// Perform the XSD validation against the specified XML document /// </summary> /// <param name="xmlLocation">The full file path of the file to be validated</param> /// <returns>True if the XML file conforms to the schemas, else false</returns> public bool IsValid(string xmlLocation) { if (!File.Exists(xmlLocation)) { throw new FileNotFoundException("The specified XML file does not exist", xmlLocation); } using (var xmlStream = File.OpenRead(xmlLocation)) { return IsValid(xmlStream); } } /// <summary> /// Perform the XSD validation against the supplied XML stream /// </summary> /// <param name="xmlStream">The XML stream to be validated</param> /// <returns>True is the XML stream conforms to the schemas, else false</returns> private bool IsValid(Stream xmlStream) { // Reset the Error/Warning collections Errors = new List<string>(); Warnings = new List<string>(); var settings = new XmlReaderSettings { ValidationType = ValidationType.Schema }; settings.ValidationEventHandler += ValidationEventHandler; foreach (var xmlSchema in Schemas) { settings.Schemas.Add(xmlSchema); } var xmlFile = XmlReader.Create(xmlStream, settings); try { while (xmlFile.Read()) { } } catch (XmlException xex) { Errors.Add(xex.Message); } return !Errors.Any() && !Warnings.Any(); } private void ValidationEventHandler(object sender, ValidationEventArgs e) { switch (e.Severity) { case XmlSeverityType.Error: Errors.Add(e.Message); break; case XmlSeverityType.Warning: Warnings.Add(e.Message); break; } } } }
The code is pretty simple but I’m a fan of hiding away any complexities so that I don’t have to think about them when I’m working on a project. The usage for this class is pretty simple as well, requiring you pass in the XSD schemas and then call IsValid specifying the XML file to validate.
public void MultipleSchemas() { var validator = new XsdValidator(); validator.AddSchema(@"SchemaDoc1.xsd"); validator.AddSchema(@"SchemaDoc2.xsd"); var isValid = validator.IsValid(@"ValidXmlDoc1.xml"); }
Both the XsdValidator and the usage example are hosted on GitHub Gists so feel free to head over to here and do what you want.
Nice – just what I needed, thanks! 🙂
good it helps me a lot
Thank You For Every Thinks
Thank you Sam for your blog and this code
nice one
For me, not working. I test with my XSD, and XML that not matches XSD and I get OK value, not KO.
This code is working for me.
using (var xtrReader = new XmlTextReader(strXsdLocation))
{
var xcSchemaCollection = new XmlSchemaCollection();
xcSchemaCollection.Add(null/*add your namespace string*/, xtrReader);
var vrValidator = new XmlValidatingReader(strXml, XmlNodeType.Document, null);
vrValidator.Schemas.Add(xcSchemaCollection);
// Add validation event handler
vrValidator.ValidationType = ValidationType.Schema;
vrValidator.ValidationEventHandler += new ValidationEventHandler(ValidationHandler);
//Actual validation, read conforming the schema.
while (vrValidator.Read()) ;
vrValidator.Close();//Cleanup
//Exception if error.
if (nErrors > 0) { throw new Exception(strErrorMsg); }
else { bStatus = true; }//Success
}
Using your code, only I added this line
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
and ALL is OK. Detect warnings and I get error in validation XML against XSD.