I\'m trying to read the data from an XML file, validating it against the XSD it suggests, into a single data structure (such as XmlDocument). I have a solution, but it requires
You're very close with your solution; what you need to do is to use a validating reader to load your XML; this way the validation is done with your loading, in one pass; validation errors will not stop you from loading the document.
These are the high level steps that I usually use with a ValidateXml helper function; it all starts with a compiled XmlSchemaSet:
public bool ValidateXml(XmlSchemaSet xset)
I set the reader settings (which you did, too):
XmlReaderSettings settings = new XmlReaderSettings { ValidationType = ValidationType.Schema, Schemas = xset, ConformanceLevel = ConformanceLevel.Document };
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
// Use your helper class that collects validation events.
XsdUtils.Utils.SmartValidationHandler svh = new XsdUtils.Utils.SmartValidationHandler(Paschi.Xml.DefaultResolver.Instance);
settings.ValidationEventHandler += svh.ValidationCallbackOne;
Then I get a reader:
XmlReader xvr = XmlReader.Create(filename, settings);
Then I read the file, which brings the validation in:
XmlDocument xdoc = new XmlDocument();
xdoc.Load(xvr);
Your validation handler has the results now; one thing I also do is to ensure that the document element that was loaded, actually has a corresponding global element definition in the xml schema set.
XmlQualifiedName qn = XmlQualifiedName.Empty;
if (xdoc.DocumentElement != null)
{
if (string.IsNullOrEmpty(xdoc.DocumentElement.NamespaceURI))
{
qn = new XmlQualifiedName(xdoc.DocumentElement.LocalName);
}
else
{
qn = new XmlQualifiedName(xdoc.DocumentElement.LocalName, xdoc.DocumentElement.NamespaceURI);
}
}
return !(svh.HasError || qn.IsEmpty || (!xset.GlobalElements.Contains(qn)));