title: Validating XML and Displaying what failed
body: <p>I am trying to validate an XML file and display any errors to the user.</p>
  
  <p>Simplified Example:</p>
  
  <p>XML:</p>
  
  <pre><code>&lt;MyApps&gt;
    &lt;MyApp&gt;
      &lt;Header&gt;
        &lt;Name&gt;Name 1&lt;/Name&gt;
        &lt;Rate&gt;4&lt;/Rate&gt;
      &lt;/Header&gt;
      &lt;Players&gt;
        &lt;Player&gt;
          &lt;Name&gt;Bert&lt;/Name&gt;
          &lt;Age&gt;22&lt;/Age&gt;
        &lt;/Player&gt;
        &lt;Player&gt;
          &lt;Name&gt;Harry&lt;/Name&gt;
          &lt;Age&gt;12&lt;/Age&gt;
        &lt;/Player&gt;
        &lt;Player&gt;
          &lt;Name&gt;George&lt;/Name&gt;
          &lt;Age&gt;16&lt;/Age&gt;
        &lt;/Player&gt;    
      &lt;/Players&gt;
    &lt;/MyApp&gt;
    &lt;MyApp&gt;
      &lt;Header&gt;
        &lt;Name&gt;Name 2&lt;/Name&gt;
        &lt;Rate&gt;3&lt;/Rate&gt;
      &lt;/Header&gt;
      &lt;Players&gt;
        &lt;Player&gt;
          &lt;Name&gt;Fred&lt;/Name&gt;
          &lt;Age&gt;29&lt;/Age&gt;
        &lt;/Player&gt;
        &lt;Player&gt;
          &lt;Name&gt;Bill&lt;/Name&gt;
          &lt;Age&gt;19&lt;/Age&gt;
        &lt;/Player&gt;
        &lt;Player&gt;
          &lt;Name&gt;Garry&lt;/Name&gt;
          &lt;Age&gt;20&lt;/Age&gt;
        &lt;/Player&gt;    
      &lt;/Players&gt;
    &lt;/MyApp&gt;
  &lt;/MyApps&gt;
  </code></pre>
  
  <p>Validator:</p>
  
  <pre><code>public class XMLValidationMessage
  {
      public int LineNumber;
      public int LinePosition;
      public string Message;
      public XmlSeverityType Severity;
  }
  public class XMLValidationResponse
  {
  
      /// &lt;summary&gt;
      /// Result of the XML Validation.
      /// &lt;/summary&gt;
      [Description("Result of the XML Validation")]
      public bool IsXMLValid { get; set; }
  
      /// &lt;summary&gt;
      /// XML Validation Errors.
      /// &lt;/summary&gt;
      [Description("XML Validation Errors")]
      public List&lt;XMLValidationMessage&gt; ValidationErrors { get; set; }
  
  
      public XMLValidationResponse()
      {
          ValidationErrors = new List&lt;XMLValidationMessage&gt;();
      }
  }
  
  
      private static XMLValidationResponse response = new XMLValidationResponse();
  
      public static XMLValidationResponse ValidateXML(string XMLFile, string XSDFile)
      {
          XmlSchemaSet schemaSet = new XmlSchemaSet();
          schemaSet.Add(null, XSDFile);
          response.IsXMLValid = true;
          Validate(XMLFile, schemaSet);
          return response;
      }
      private static void Validate(String filename, XmlSchemaSet schemaSet)
      {
  
          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();
      }
  
      private static void ValidationCallBack(object sender, ValidationEventArgs args)
      {
          response.IsXMLValid = false;
          if (args.Severity == XmlSeverityType.Warning)
          {
              XMLValidationMessage xmlm = new XMLValidationMessage();
              xmlm.Severity = XmlSeverityType.Warning;
              xmlm.LineNumber = 0;
              xmlm.LinePosition = 0;
              xmlm.Message = "Matching schema not found.  No validation occurred.";
              response.ValidationErrors.Add(xmlm);
          }
          else
          {
              XMLValidationMessage xmlm = new XMLValidationMessage();
              xmlm.Severity = XmlSeverityType.Error;
              xmlm.LineNumber = args.Exception.LineNumber;
              xmlm.LinePosition = args.Exception.LinePosition;
              xmlm.Message = args.Message;
              response.ValidationErrors.Add(xmlm);
          }
  
      }
  </code></pre>
  
  <p>If the XML fails validation I get a List of errors in the form of <code>XMLValidationMessage</code>.  This gives me a line number, Line position and message.  However, there seems to be no way to link the error to the XML element that caused the error.  After validation I deserialise the XML into a data class object then use this to populate a tree view.  Ultimately what I want to do is highlight the branches of the treeview that failed validation.  I am thinking that maybe I am going about this the wrong way?  </p>
  
  <p><strong>Update - Example Error</strong></p>
  
  <pre><code>ValidationErrors    Count = 14  System.Collections.Generic.List&lt;MyApp.Xml.XMLValidationMessage&gt;
  -   [0] {MyApp.Xml.XMLValidationMessage}    MyApp.Xml.XMLValidationMessage
      LineNumber  89  int
      LinePosition    127 int
      Message "The 'http://www.myweb.co.uk/srm/mscc:Remarks' element is invalid - The value 'Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...' is invalid according to its datatype 'http://www.MyWeb.co.uk/srm/mscc:String50Type' - The actual length is greater than the MaxLength value."    string
      Severity    Error   System.Xml.Schema.XmlSeverityType
  </code></pre>
  
  <p>I get a collection of errors that are all valid errors. Not sure if the Schema would help that part is working fine.  The trouble I am haiving is linking the error to the XML element causing the error.</p>