Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I force compliance with a given schema in .NET?

Let's say I have a schema with which I want an input document to comply. I load the file according to the schema like this:

// Load the ABC XSD
var schemata = new XmlSchemaSet();
string abcSchema = FooResources.AbcTemplate;
using (var reader = new StringReader(abcSchema))
using (var schemaReader = XmlReader.Create(reader))
{
    schemata.Add(string.Empty, schemaReader);
}

// Load the ABC file itself
var settings = new XmlReaderSettings
{
    CheckCharacters = true,
    CloseInput = false,
    ConformanceLevel = ConformanceLevel.Document,
    IgnoreComments = true,
    Schemas = schemata,
    ValidationType = ValidationType.Schema,
    ValidationFlags = XmlSchemaValidationFlags.ReportValidationWarnings
};

XDocument inputDoc;
try
{
    using (var docReader = XmlReader.Create(configurationFile, settings))
    {
        inputDoc = XDocument.Load(docReader);
    }
}
catch (XmlSchemaException xsdViolation)
{
    throw new InvalidDataException(".abc file format constraint violated.", xsdViolation);
}

This works fine in detecting trivial errors in the file. However, because the schema is locked to a namespace, a document like the following is invalid, but sneaks through:

<badDoc xmlns="http://Foo/Bar/Bax">
  This is not a valid document; but Schema doesn't catch it
  because of that xmlns in the badDoc element.
</badDoc>

I would like to say that only the namespaces for which I have schemata should pass schema validation.

like image 658
Billy ONeal Avatar asked Feb 26 '13 20:02

Billy ONeal


2 Answers

As stupid as it seems, the thing you want to look at is actually on the XmlReaderSettings object:

settings.ValidationEventHandler += 
    (node, e) => Console.WriteLine("Bad node: {0}", node);
like image 187
JerKimball Avatar answered Sep 19 '22 08:09

JerKimball


The solution I ended up settling on is to basically check that the root node is in the namespace I expect. If it isn't, then I treat that the same way I treat a true schema validation failure:

// Parse the bits we need out of that file
var rootNode = inputDoc.Root;
if (!rootNode.Name.NamespaceName.Equals(string.Empty, StringComparison.Ordinal))
{
    throw new InvalidDataException(".abc file format namespace did not match.");
}
like image 39
Billy ONeal Avatar answered Sep 19 '22 08:09

Billy ONeal