with validator validate validar net error con c# xml xsd xml-validation

validate - xml validator c#



Comenzando con la validaciĆ³n XSD con.NET (3)

En lugar de utilizar el método de extensión XDocument.Validate , usaría un XmlReader que se puede configurar para procesar un esquema en línea a través de XmlReaderSettings . Podrías hacer algo como el siguiente código.

public void VerifyXmlFile(string path) { // configure the xmlreader validation to use inline schema. XmlReaderSettings config = new XmlReaderSettings(); config.ValidationType = ValidationType.Schema; config.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings; config.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema; config.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation; config.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack); // Get the XmlReader object with the configured settings. XmlReader reader = XmlReader.Create(path, config); // Parsing the file will cause the validation to occur. while (reader.Read()) ; } private void ValidationCallBack(object sender, ValidationEventArgs vea) { if (vea.Severity == XmlSeverityType.Warning) Console.WriteLine( "/tWarning: Matching schema not found. No validation occurred. {0}", vea.Message); else Console.WriteLine("/tValidation error: {0}", vea.Message); }

El código anterior asume las siguientes declaraciones de uso.

using System.Xml; using System.Xml.Schema;

Solo para mantener esto simple no boolean un error boolean o una colección de errores de validación, podría modificarlo fácilmente para hacerlo.

Nota: modifiqué tu config.xml y config.xsd para que se validen. Estos son los cambios que hice.

config.xsd:

<xs:element maxOccurs="unbounded" name="levelVariant">

config.xml:

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="config.xsd">

Aquí está mi primer intento de validar XML con XSD.

El archivo XML a validar:

<?xml version="1.0" encoding="utf-8" ?> <config xmlns="Schemas" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="config.xsd"> <levelVariant> <filePath>SampleVariant</filePath> </levelVariant> <levelVariant> <filePath>LegendaryMode</filePath> </levelVariant> <levelVariant> <filePath>AmazingMode</filePath> </levelVariant> </config>

El XSD, ubicado en "Schemas / config.xsd" en relación con el archivo XML a validar:

<?xml version="1.0" encoding="utf-8" ?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <xs:element name="config"> <xs:complexType> <xs:sequence> <xs:element name="levelVariant"> <xs:complexType> <xs:sequence> <xs:element name="filePath" type="xs:anyURI"> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>

En este momento, solo quiero validar el archivo XML exactamente como aparece actualmente. Una vez que entienda esto mejor, ampliaré más. ¿Realmente necesito tantas líneas para algo tan simple como el archivo XML tal como existe actualmente?

El código de validación en C #:

public void SetURI(string uri) { XElement toValidate = XElement.Load(Path.Combine(PATH_TO_DATA_DIR, uri) + ".xml"); // begin confusion // exception here string schemaURI = toValidate.Attributes("xmlns").First().ToString() + toValidate.Attributes("xsi:noNamespaceSchemaLocation").First().ToString(); XmlSchemaSet schemas = new XmlSchemaSet(); schemas.Add(null, schemaURI); XDocument toValidateDoc = new XDocument(toValidate); toValidateDoc.Validate(schemas, null); // end confusion root = toValidate; }

Ejecutar el código anterior da esta excepción:

The '':'' character, hexadecimal value 0x3A, cannot be included in a name.

Cualquier iluminación sería apreciada.


Lo siguiente está fuera de una muestra de trabajo:

Uso:

XMLValidator val = new XMLValidator(); if (!val.IsValidXml(File.ReadAllText(@"d:/Test2.xml"), @"D:/Test2.xsd")) MessageBox.Show(val.Errors);

Clase:

public class CXmlValidator { private int nErrors = 0; private string strErrorMsg = string.Empty; public string Errors { get { return strErrorMsg; } } public void ValidationHandler(object sender, ValidationEventArgs args) { nErrors++; strErrorMsg = strErrorMsg + args.Message + "/r/n"; } public bool IsValidXml(string strXml/*xml in text*/, string strXsdLocation /*Xsd location*/) { bool bStatus = false; try { // Declare local objects XmlTextReader xtrReader = new XmlTextReader(strXsdLocation); XmlSchemaCollection xcSchemaCollection = new XmlSchemaCollection(); xcSchemaCollection.Add(null/*add your namespace string*/, xtrReader);//Add multiple schemas if you want. XmlValidatingReader 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 } catch (Exception error) { bStatus = false; } return bStatus; } }

El código anterior valida el siguiente xml (code3) contra xsd (code4).

<!--CODE 3 - TEST1.XML--> <address xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Test1.xsd"> <name>My Name</name> <street>1, My Street Address</street> <city>Far</city> <country>Mali</country> </address> <!--CODE 4 - TEST1.XSD--> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="address"> <xs:complexType> <xs:sequence> <xs:element name="name" type="xs:string"/> <xs:element name="street" type="xs:string"/> <xs:element name="city" type="xs:string"/> <xs:element name="country" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>

Al validar contra tu xml / xsd obtengo errores diferentes a los tuyos; Creo que esto puede ayudarte a continuar (agregar / eliminar elementos xml) desde aquí:

Errores http://www.freeimagehosting.net/uploads/01a570ce8b.jpg

También puede probar el proceso inverso; intente generar el esquema desde su xml y compare con su xsd real - vea la diferencia; y la forma más sencilla de hacerlo es usar el esquema de generación utilizando VS IDE. Lo siguiente es cómo harías eso:

Cree XSD desde XML http://i44.tinypic.com/15yhto3.jpg

Espero que esto ayude.

--EDITAR--

Esto es a petición de John, vea el código actualizado usando métodos no obsoletos:

public bool IsValidXmlEx(string strXmlLocation, string strXsdLocation) { bool bStatus = false; try { // Declare local objects XmlReaderSettings rs = new XmlReaderSettings(); rs.ValidationType = ValidationType.Schema; rs.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation | XmlSchemaValidationFlags.ReportValidationWarnings; rs.ValidationEventHandler += new ValidationEventHandler(rs_ValidationEventHandler); rs.Schemas.Add(null, XmlReader.Create(strXsdLocation)); using (XmlReader xmlValidatingReader = XmlReader.Create(strXmlLocation, rs)) { while (xmlValidatingReader.Read()) { } } ////Exception if error. if (nErrors > 0) { throw new Exception(strErrorMsg); } else { bStatus = true; }//Success } catch (Exception error) { bStatus = false; } return bStatus; } void rs_ValidationEventHandler(object sender, ValidationEventArgs e) { if (e.Severity == XmlSeverityType.Warning) strErrorMsg += "WARNING: " + Environment.NewLine; else strErrorMsg += "ERROR: " + Environment.NewLine; nErrors++; strErrorMsg = strErrorMsg + e.Exception.Message + "/r/n"; }

Uso:

if (!val.IsValidXmlEx(@"d:/Test2.xml", @"D:/Test2.xsd")) MessageBox.Show(val.Errors); else MessageBox.Show("Success");

Test2.XML

<?xml version="1.0" encoding="utf-8" ?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Test2.xsd"> <levelVariant> <filePath>SampleVariant</filePath> </levelVariant> <levelVariant> <filePath>LegendaryMode</filePath> </levelVariant> <levelVariant> <filePath>AmazingMode</filePath> </levelVariant> </config>

Test2.XSD (generado a partir de VS IDE)

<?xml version="1.0" encoding="utf-8" ?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <xs:element name="config"> <xs:complexType> <xs:sequence> <xs:element maxOccurs="unbounded" name="levelVariant"> <xs:complexType> <xs:sequence> <xs:element name="filePath" type="xs:anyURI"> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>

Esto está garantizado para trabajar!


Tu código para extraer la ubicación del esquema parece extraño. ¿Por qué obtiene el valor del atributo xmlns y lo concatena con el valor del atributo xsi: noNamespaceSchemaLocation? La excepción se debe al hecho de que no puede especificar un prefijo en una llamada a Atributos; necesitas especificar el XNamespace deseado.

Prueba esto (sin probar):

// Load document XDocument doc = XDocument.Load("file.xml"); // Extract value of xsi:noNamespaceSchemaLocation XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance"; string schemaURI = (string)doc.Root.Attribute(xsi + "noNamespaceSchemaLocation"); // Create schema set XmlSchemaSet schemas = new XmlSchemaSet(); schemas.Add("Schemas", schemaURI); // Validate doc.Validate(schemas, (o, e) => { Console.WriteLine("{0}", e.Message); });