2009-11-10 30 views
9

Używam XmlSerializer do deserializacji osi Xml. Ale znalazłem klasy xsd.exe generowane tylko oferty możliwości odczytu xml, ale bez sprawdzania poprawności. Jeśli na przykład brakuje jednego węzła w dokumencie, pole atrybutu wygenerowanej klasy będzie miało wartość NULL, a nie zgłasza wyjątek sprawdzania poprawności zgodnie z oczekiwaniami. Jak mogę to osiągnąć? Dzięki!Walidacja xmlserializer

Odpowiedz

26

Poniższy kod powinien sprawdzać poprawność względem schematu podczas przekształcania deserializacji. Podobny kod może być użyty do sprawdzania poprawności względem schematu podczas serializacji.

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

Dziękujemy za udostępnienie tego rozwiązania. Ponieważ to sprawia, że ​​walidacja jest zgodna z deserializacją poprzez sprawdzanie poprawności za pomocą XmlReader, jest to lepsze podejście. – el2iot2

4

Poniższy kod spowoduje ręczne załadowanie i weryfikację pliku XML względem pliku schematu programowo, co pozwala na obsługę dowolnej wersji 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 
     } 
    )); 
} 

Teraz oczywiście chcecie mieć klas generowanych przez xsd.exe to zrobić automatycznie, a podczas ładowania (powyższe podejście wymagałoby drugą manipulację pliku XML), ale validate pre-load pozwoliłby programowo wykryć zniekształcony plik wejściowy.

+0

@John Saunders - mam wątpliwości, że kod generacji klasy jest prawdopodobne, aby zmienić jego działanie w najbliższym czasie, a strona msdn nie wykazuje odpowiednie opcje dla xsd.exe, więc myślę, że to rozsądne, aby zaproponować obejście ... – el2iot2

+1

W tekście pytania PO wyraża życzenie, aby zgłosił wyjątek dla nieprawidłowego pliku wejściowego xml. Takie podejście pozwala to osiągnąć. Nie twierdzę, że jest to jedyny sposób, w jaki można to zrobić, a nawet, że jest to najlepszy sposób. Ale odpowiadałem podejściem (z góry mojej głowy), którego używałem w przeszłości do ogólnego sprawdzania dokumentów XML. – el2iot2