Paul Turner
Paul Turner

Reputation: 39675

Compiling an XmlSchemaSet with imported schemas

I'm trying to create an XmlSchemaSet against the SAML 2.0 set of schema definitions, starting with the protocol schema here: https://docs.oasis-open.org/security/saml/v2.0/saml-schema-protocol-2.0.xsd

var set = new XmlSchemaSet();

XmlSchema schema;
using (var reader = XmlReader.Create(
    "https://docs.oasis-open.org/security/saml/v2.0/saml-schema-protocol-2.0.xsd"))
{
    schema = XmlSchema.Read(reader, (sender, e) => Console.WriteLine(e.Message));
}

set.Add(schema);

set.Compile();

When Compile is called, the following exception is thrown:

System.Xml.Schema.XmlSchemaException
Type 'urn:oasis:names:tc:SAML:2.0:assertion:EncryptedElementType' is not declared.
   at System.Xml.Schema.XmlSchemaSet.InternalValidationCallback(Object sender, ValidationEventArgs e)
   at System.Xml.Schema.BaseProcessor.SendValidationEvent(XmlSchemaException e, XmlSeverityType severity)
   at System.Xml.Schema.BaseProcessor.SendValidationEvent(XmlSchemaException e)
   at System.Xml.Schema.Compiler.CompileElement(XmlSchemaElement xe)
   at System.Xml.Schema.Compiler.Compile()
   at System.Xml.Schema.Compiler.Execute(XmlSchemaSet schemaSet, SchemaInfo schemaCompiledInfo)
   at System.Xml.Schema.XmlSchemaSet.Compile()
   at XSD.Program.Main(String[] args)

The type specified urn:oasis:names:tc:SAML:2.0:assertion:EncryptedElementType appears in the namespace imported at the top of the schema:

<import
    namespace="urn:oasis:names:tc:SAML:2.0:assertion"
    schemaLocation="saml-schema-assertion-2.0.xsd"/>

Using Fiddler, I can't see the application making any attempts at retrieving the imported schema.

Why don't these import statements appear to be working with the XmlSchemaSet?

Upvotes: 3

Views: 2145

Answers (1)

Paul Turner
Paul Turner

Reputation: 39675

The default behaviour of the XmlSchemaSet is to not try to resolve any external schemas. To this this, the XmlResolver property must be set. The go-to resolver implementation is XmlUrlResolver:

set.XmlResolver = new XmlUrlResolver();

The important thing is to set this property before adding any schemas to the set. The call to Add performs "pre-processing" on the schema, which includes resolving any import statements. Assigning the XmlResolver after calling Add appears to have no effect.

The application code needs to be:

var set = new XmlSchemaSet
{
    // Enable resolving of external schemas.
    XmlResolver = new XmlUrlResolver()
};

XmlSchema schema;
using (var reader = XmlReader.Create(
    "https://docs.oasis-open.org/security/saml/v2.0/saml-schema-protocol-2.0.xsd"))
{
    schema = XmlSchema.Read(reader, (sender, e) => Console.WriteLine(e.Message));
}

set.Add(schema);

set.Compile();

NOTE The above code still does not actually produce the desired result due to problems loading the schemas from w3.org, however the imported SAML schema is resolved successfully.

Upvotes: 6

Related Questions