Validando um XML em relação ao XSD referenciado em c #

Eu tenho um arquivo XML com um local de esquema especificado como este:

xsi:schemaLocation="someurl ..\localSchemaPath.xsd" 

Eu quero validar em c #. Visual Studio, quando abro o arquivo, valida-o contra o esquema e lista os erros perfeitamente. De alguma forma, no entanto, parece que não consigo validar automaticamente em C # sem especificar o esquema para validar da seguinte forma:

 XmlDocument asset = new XmlDocument(); XmlTextReader schemaReader = new XmlTextReader("relativeSchemaPath"); XmlSchema schema = XmlSchema.Read(schemaReader, SchemaValidationHandler); asset.Schemas.Add(schema); asset.Load(filename); asset.Validate(DocumentValidationHandler); 

Eu não deveria ser capaz de validar com o esquema especificado no arquivo XML automaticamente? O que estou perdendo ?

Você precisa criar uma instância de XmlReaderSettings e passar isso para o seu XmlReader ao criá-lo. Então você pode se inscrever no ValidationEventHandler nas configurações para receber erros de validação. Seu código terminará assim:

 using System.Xml; using System.Xml.Schema; using System.IO; public class ValidXSD { public static void Main() { // Set the validation settings. XmlReaderSettings settings = new XmlReaderSettings(); settings.ValidationType = ValidationType.Schema; settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema; settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation; settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings; settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack); // Create the XmlReader object. XmlReader reader = XmlReader.Create("inlineSchema.xml", settings); // Parse the file. while (reader.Read()) ; } // Display any warnings or errors. 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); } } 

Uma maneira mais simples, se você estiver usando o .NET 3.5, é usar a validação XDocument e XmlSchemaSet .

 XmlSchemaSet schemas = new XmlSchemaSet(); schemas.Add(schemaNamespace, schemaFileName); XDocument doc = XDocument.Load(filename); string msg = ""; doc.Validate(schemas, (o, e) => { msg += e.Message + Environment.NewLine; }); Console.WriteLine(msg == "" ? "Document is valid" : "Document invalid: " + msg); 

Consulte a documentação da MSDN para obter mais assistência.

O exemplo a seguir valida um arquivo XML e gera o erro ou aviso apropriado.

 using System; using System.IO; using System.Xml; using System.Xml.Schema; public class Sample { public static void Main() { //Load the XmlSchemaSet. XmlSchemaSet schemaSet = new XmlSchemaSet(); schemaSet.Add("urn:bookstore-schema", "books.xsd"); //Validate the file using the schema stored in the schema set. //Any elements belonging to the namespace "urn:cd-schema" generate //a warning because there is no schema matching that namespace. Validate("store.xml", schemaSet); Console.ReadLine(); } private static void Validate(String filename, XmlSchemaSet schemaSet) { Console.WriteLine(); Console.WriteLine("\r\nValidating XML file {0}...", filename.ToString()); XmlSchema compiledSchema = null; foreach (XmlSchema schema in schemaSet.Schemas()) { compiledSchema = schema; } XmlReaderSettings settings = new XmlReaderSettings(); settings.Schemas.Add(compiledSchema); settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack); settings.ValidationType = ValidationType.Schema; //Create the schema validating reader. XmlReader vreader = XmlReader.Create(filename, settings); while (vreader.Read()) { } //Close the reader. vreader.Close(); } //Display any warnings or errors. 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); } } 

O exemplo anterior usa os seguintes arquivos de input.

 < ?xml version='1.0'?>   The Confidence Man 11.99   Americana Offspring 16.95   

books.xsd

                       

Eu fiz esse tipo de validação automática no VB e é assim que eu fiz isso (convertido para C #):

 XmlReaderSettings settings = new XmlReaderSettings(); settings.ValidationType = ValidationType.Schema; settings.ValidationFlags = settings.ValidationFlags | Schema.XmlSchemaValidationFlags.ProcessSchemaLocation; XmlReader XMLvalidator = XmlReader.Create(reader, settings); 

Então eu me inscrevi para o evento settings.ValidationEventHandler ao ler o arquivo.

pessoalmente eu sou a favor de validar sem um retorno de chamada:

 public bool ValidateSchema(string xmlPath, string xsdPath) { XmlDocument xml = new XmlDocument(); xml.Load(xmlPath); xml.Schemas.Add(null, xsdPath); try { xml.Validate(null); } catch (XmlSchemaValidationException) { return false; } return true; } 

(veja a publicação de Timiz0r na Validação de Esquema XML Síncrona? .NET 3.5 )

Exemplo do MSDN usando LINQ to XML