Resolve External XML Resources Named by a URI

XmlResolver is an abstract class that locates external XML resources that have been named by a URI. The XmlResolver class is used by the following classes:

  • XmlTextReader: to load an XML document and external DTDs.
  • XmlValidatingReader: to load an XML document, external DTDs, entities, and schemas.
  • XmlDocument: to load an XML document, external DTDs and entities.
  • XmlSchema: to process <xs:include> and <xs:import> elements.
  • XmlSchemaCollection: to process <xs:include> and <xs:import> elements.
  • XslTransform: to load the style sheet, process <xsl:include> or <xsl:import> elements found in the style sheet, and to resolve any document() functions found in the style sheet.

The XmlResolver class facilitates resolving XML resources from arbitrary sources of data such as file systems and Web servers. The concrete implementations of XmlResolver handle all aspects of negotiating the connection to the resources, including handling security credentials, opening the connection to the data source, and returning the resource in the form of a stream or other object type.

The XmlUrlResolver class is a concrete implementation of XmlResolver for URLs. This class facilitates resolving XML resources using the file://, http://, and https:// protocols.

The XmlSecureResolver, implemented in .NET Framework version 1.1, is another concrete implementation of the XmlResolver. The XmlSecureResolver is used to wrap around any concrete implementation of XmlResolver, and restricts the resources that the underlying XmlResolver has access to through security permissions. For instance, XmlSecureResolver has the ability to prohibit cross-domain redirection, which can occur from an embedded URI reference.

The XmlSecureResolver derrived class enables you to set a PermissionSet to only permit access to desired resources. By setting the appropriate security permissions, the underlying XmlResolver is not able to access resources that do not comply with the .NET security model.

In .NET Framework version 1.1, XmlSecureResolver has three overloaded constructors. The first one takes an XmlResolver and Evidence as arguments, and the second method takes an XmlResolver and PermissionSet as arguments, and the third takes XmlResolver and a URI string.

When a method that does not provide a PermissionSet argument is used, the Evidence or URI is used to calculate the PermissionSet to assert on the underlying XmlResolver. If you know what PermissionSet you want the XmlSecureResolver to have, or you want a more customized PermissionSet, use the third overloaded method which enables you to directly assert the given PermissionSet to the underlying XmlResolver. For more information on the overloaded XmlSecureResolver methods, see XmlSecureResolver Constructor.

Finding the Absolute URI of an XML Resource

If you have a relative URI and a base URI, you can call the ResolveUri method of the XmlResolver class and have it return the absolute URI of your resource. To use this method, call the XmlResolver.ResolveUri method giving it the base URI, and the URI to resolve, and it returns an absolute URI. Once you have the absolute URI, you can call the GetEntity method of an XmlResolver to get access to the resource identified by the URI. The GetEntity method uses the absolute URI to locate and return a stream object for the resource.

Using the Resolver to Locate Resources Used by a Transform and the XslTransform Class

If an XSLT style sheet contains an <xsl:import> or <xsl:include> tag, or a document() function, then an XmlResolver implementation is used to locate the external resource.

XslTransform xslt = new XslTransform();
xslt.Load("http://webdata/global/xmlweb.xsl", new XmlUrlResolver());

While compiling the xmlweb.xsl style sheet, the XslTransform finds an include element as follows:

<xsl:include href="managed.xsl"/">

So the XslTransform calls

Uri fulluri = this.XmlResolver.ResolveUri("http://webdata/global/xmlweb.xsl",
                                    "managed.xsl");
if (fulluri != null) {
    Stream s = (Stream)this.XmlResolver.GetEntity(fulluri, null,
                                                 typeof(Stream));
}

This returns a new stream, which it wraps in an XmlTextReader and continues on compiling the included style sheet. Note that the XslTransform class passes forward the XmlResolver instance it was originally supplied with in the Load method to ensure that XmlTextReader can resolve resources with the same security privileges.

[C#]

XmlTextReader reader = new XmlTextReader(s, fulluri);
reader.XmlResolver = this.XmlResolver;
while (reader.Read()) 
{ . . .}

In .NET Framework version 1.1, if you want to prevent cross zone redirection, or prevent access to certain XSLT style sheets that are located at a particular URI, this is enforced by setting the security policy of the machine appropriately, and supplying the XmlSecureResolver to the Load and Transform methods on the XslTransform class. In .NET Framework version 1.0, there is no way to prevent cross-zone or cross-domain redirection checking. This means that any embedded URI that causes redirection caused by includes, imports, referencing external entities, and so on, will read the data without checking any kind of security on the data or site. This is because no credentials are passed when the redirection occurs, and therefore, your style sheet can be compromised by obtaining data from an insecure or anonymous site.

See Also

Resolving Resources using the XmlResolver | Supplying Authentication Credentials to XmlResolver when Reading from a File | Creating a Custom Resolver