2009-11-10 10 views
9

Estoy usando XmlSerializer para deserializar Xml Achives. Pero encontré que la clase xsd.exe generada solo ofrece la capacidad de leer el xml, pero no la validación. Por ejemplo, si falta un nodo en un documento, el campo de atributo de la clase generada será nulo, en lugar de arrojar una excepción de validación como esperaba. ¿Cómo puedo lograr eso? ¡Gracias!xmlserializer validation

Respuesta

26

El siguiente código debe validar contra un esquema mientras se deserializa. Se puede usar un código similar para validar frente a un esquema durante la serialización.

private static Response DeserializeAndValidate(string tempFileName) 
{ 
    XmlSchemaSet schemas = new XmlSchemaSet(); 
    schemas.Add(LoadSchema()); 

    Exception firstException = null; 

    var settings = new XmlReaderSettings 
        { 
         Schemas = schemas, 
         ValidationType = ValidationType.Schema, 
         ValidationFlags = 
          XmlSchemaValidationFlags.ProcessIdentityConstraints | 
          XmlSchemaValidationFlags.ReportValidationWarnings 
        }; 
    settings.ValidationEventHandler += 
     delegate(object sender, ValidationEventArgs args) 
     { 
      if (args.Severity == XmlSeverityType.Warning) 
      { 
       Console.WriteLine(args.Message); 
      } 
      else 
      { 
       if (firstException == null) 
       { 
        firstException = args.Exception; 
       } 

       Console.WriteLine(args.Exception.ToString()); 
      } 
     }; 

    Response result; 
    using (var input = new StreamReader(tempFileName)) 
    { 
     using (XmlReader reader = XmlReader.Create(input, settings)) 
     { 
      XmlSerializer ser = new XmlSerializer(typeof (Response)); 
      result = (Response) ser.Deserialize(reader); 
     } 
    } 

    if (firstException != null) 
    { 
     throw firstException; 
    } 

    return result; 
} 
+2

Gracias por compartir esta solución. Como esto pone la validación en línea con la deserialización mediante la validación a través de XmlReader, es un mejor enfoque. – el2iot2

4

El siguiente código cargará y validará su XML manualmente contra un archivo de esquema mediante programación, lo que le permite tratar cualquier resulting errors and/or warnings.

//Read in the schema document 
using (XmlReader schemaReader = XmlReader.Create("schema.xsd")) 
{ 
    XmlSchemaSet schemaSet = new XmlSchemaSet(); 

    //add the schema to the schema set 
    schemaSet.Add(XmlSchema.Read(schemaReader, 
    new ValidationEventHandler(
     delegate(Object sender, ValidationEventArgs e) 
     { 
     }  
    ))); 

    //Load and validate against the programmatic schema set 
    XmlDocument xmlDocument = new XmlDocument(); 
    xmlDocument.Schemas = schemaSet; 
    xmlDocument.Load("something.xml"); 

    xmlDocument.Validate(new ValidationEventHandler(
     delegate(Object sender, ValidationEventArgs e) 
     { 
      //Report or respond to the error/warning 
     } 
    )); 
} 

Ahora es obvio que el deseo de tener las clases generadas por xsd.exe hacer esto de forma automática y durante la carga (el enfoque anterior requeriría una segunda manejo del archivo XML), sino una validación precarga permitiría usted para detectar mediante programación un archivo de entrada mal formado.

+0

@ John Saunders - Estoy dudando de que el código de generación de la clase es probable que cambie su funcionamiento en el corto plazo, y el sitio de MSDN no muestra opciones relevantes para xsd.exe, así que creo que es razonable sugerir una solución alternativa ... – el2iot2

+1

En el texto de la pregunta, el OP expresa que quiere que se genere una excepción para un xml de entrada no válido. Este enfoque logra eso. No estoy afirmando que esta es la única forma en que se puede hacer, o incluso que es la mejor manera. Pero estaba respondiendo con un enfoque (fuera de lo común) que había utilizado en el pasado para validar documentos XML en general. – el2iot2