11

The following code helps me validate an XML file with an XSD schema.

XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add(null, xsdFilePath);
settings.ValidationType = ValidationType.Schema;
settings.ValidationEventHandler += new System.Xml.Schema.ValidationEventHandler(settings_ValidationEventHandler);
XmlDocument document = new XmlDocument();
document.Load(xmlFilePath);
XmlReader rdr = XmlReader.Create(new StringReader(document.InnerXml), settings);

while (rdr.Read())
{

}
isValid = true;

The ValidationEventHandler also tells me what the errors are, but doesn't tell me on 'where' or 'on which line' they are located. Is there any way to get the line number where the XML fails to be validated?

Davide Piras
  • 43,984
  • 10
  • 98
  • 147
Elroy
  • 605
  • 4
  • 12
  • 20

2 Answers2

28

Would not this do what you are after ?

Create an XmlReaderSettings object and enable warnings through that object.

Unfortunately, there seems to be no way to pass your own XmlReaderSettings object to XmlDocument.Validate().
Instead, you can use a validating XmlReader and an XmlNodeReader to validate an existing XmlDocument (using a XmlNodeReader with StringReader rather than an XmlDocument)

XmlDocument x = new XmlDocument();
x.LoadXml(XmlSource);

XmlReaderSettings settings = new XmlReaderSettings();
settings.CloseInput = true;     
settings.ValidationEventHandler += Handler;

settings.ValidationType = ValidationType.Schema;
settings.Schemas.Add(null, ExtendedTreeViewSchema);
settings.ValidationFlags =
     XmlSchemaValidationFlags.ReportValidationWarnings |
XmlSchemaValidationFlags.ProcessIdentityConstraints |
XmlSchemaValidationFlags.ProcessInlineSchema |
XmlSchemaValidationFlags.ProcessSchemaLocation ;

StringReader r = new StringReader(XmlSource);

using (XmlReader validatingReader = XmlReader.Create(r, settings)) {
        while (validatingReader.Read()) { /* just loop through document */ }
}

And the handler:

private static void Handler(object sender, ValidationEventArgs e)
{
        if (e.Severity == XmlSeverityType.Error || e.Severity == XmlSeverityType.Warning)
          System.Diagnostics.Trace.WriteLine(
            String.Format("Line: {0}, Position: {1} \"{2}\"",
                e.Exception.LineNumber, e.Exception.LinePosition, e.Exception.Message));
}
Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 2
    +1 Completely missed e.Exception.LineNumber and e.Exception.LinePosition. – Elroy Feb 21 '09 at 12:23
  • Why are you putting this into an XmlDocument at the beginning? It does not seem to do anything. – Jeremy Holovacs Apr 09 '12 at 16:08
  • @JeremyHolovacs true, it was just a copy of one of the answers of the 2007 forum (http://www.devnewsgroups.net/dotnetframework/t43762-catching-line-numbers-with-xmldocument-validate.aspx), and the following comment mentioned: "It works when I do away with the `XmlDocument` and replace `XmlNodeReader` with `StringReader`" – VonC Apr 09 '12 at 16:17
3

ValidationEventArgs.Message includes line/column in its text.

ValidationEventArgs.Exception has fields for line and column.

Richard
  • 106,783
  • 21
  • 203
  • 265