Is there any way to validate an XML file on an XSD schema with the output of the error line numbers?
The XmlReader reader doesn\'t allow line numbers, it shows only
Woah, rather tricky this XSD stuff, I'm also new :)
As it was said before the position information gets lost in the XmlDocument.
I got it finally running using the XmlReader in combination with XmlDocument:
// xmlStream and xsdStream are open streams that
// point to the respective xml and xsd files
public void ReadAndVerify(Stream xmlStream, Stream xsdStream)
{
// Read the scheme validation and compile it
XmlSchemaSet schemaSet = new XmlSchemaSet();
using (XmlReader r = XmlReader.Create(xsdStream))
{
schemaSet.Add(XmlSchema.Read(r, null));
}
schemaSet.CompilationSettings = new XmlSchemaCompilationSettings();
schemaSet.Compile();
// Setup the settings for the reader.
// This includes the previously compiled schema
XmlReaderSettings settings = new XmlReaderSettings();
settings.CloseInput = true;
// This is the callback method see below
settings.ValidationEventHandler += ValidationEventHandler;
settings.ValidationType = ValidationType.Schema;
settings.Schemas = schemaSet; // <-- here the schema is set
// To be honest, this is cut'n'paste. Not sure which flags are really required.
settings.ValidationFlags =
XmlSchemaValidationFlags.ReportValidationWarnings |
XmlSchemaValidationFlags.ProcessIdentityConstraints |
XmlSchemaValidationFlags.ProcessInlineSchema |
XmlSchemaValidationFlags.ProcessSchemaLocation;
// Now the validating reader is created
using (XmlReader validatingReader = XmlReader.Create(xmlStream, settings))
{
// This has to be done BEFORE the validating while loop
XmlDocument x = new XmlDocument();
x.Load(validatingReader);
// This is the validation loop
while (validatingReader.Read()) ;
// This is the client code that actually uses the XmlDocument nodes.
XmlNode node = x[RootNode];
ReadAllParameters(node);
}
}
And the ValidationEventHandler:
private void ValidationEventHandler(object sender, ValidationEventArgs e)
{
// This actually works with this approach
string text = $"[Line: {e.Exception?.LineNumber}, Column: {e.Exception?.LinePosition}]: {e.Message}";
switch (e.Severity) {
case XmlSeverityType.Error:
Logger.Error(text);
break;
case XmlSeverityType.Warning:
Logger.Warn(e.Message);
break;
}
}
Life can be so simple ;-)