Thursday, June 14, 2007

XSL Transforms and Included/Imported Sheets with DTDs

Problem: Loading an XSL sheet with DTDs defined in it barfs because by default DTDs aren’t allowed in XSL for security reasons.

Solution: Load the XSL sheet with an XmlReader which has its ProhibitDtd property set to false:

XmlReaderSettings readerSettings = new XmlReaderSettings();

readerSettings.ProhibitDtd = false;

XmlReader xslReader = XmlReader.Create(XSLSHEET, readerSettings);

XslCompiledTransform xform = new XslCompiledTransform();

xform.Load(xslReader);

That's fine and ducky if you're working with an XSL sheet which doesn’t import or include any other sheets.  Unfortunately, I’m working with DocBook’s html sheets which do indeed import a metric crapload of other sheets.  Those downstream sheets get resolved and loaded with default XmlReaders which don’t carry along the ProhibitDtd property.

Ugh.

More Better Solution: Write a custom XmlResolver which returns an XmlReader with the ProhibitDtd property set false:

public class XmlReaderResolver : XmlResolver

{

    private System.Net.ICredentials credentials;

    private XmlReaderSettings settings;

 

    public XmlReaderSettings Settings

    {

        get { return settings; }

        set { settings = value; }

    }

 

    public XmlReaderResolver()

    {

        settings = new XmlReaderSettings();

        settings.ProhibitDtd = false;

        settings.ConformanceLevel = ConformanceLevel.Fragment;

 

        credentials = CredentialCache.DefaultCredentials;

    }

 

    public override System.Net.ICredentials Credentials

    {

        set { credentials = value; }

    }

 

    public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)

    {

        XmlReader reader = XmlReader.Create(absoluteUri.ToString(), settings);

        return reader;

    }

}

Now that custom resolver as you’re loading the XSL (partial snipped along the same lines as above):

MyXmlResolver resolver = new MyXmlResolver();

 

XsltSettings xsltSettings = new XsltSettings();

xsltSettings.EnableDocumentFunction = true;

 

xform.Load(xslReader, xsltSettings, resolver);

So far this seems to be working well, although I've got other issues with how the various XmlReaders and XmlWriters aren't playing overly nicely with the XML content I'm holding in memory. More on that later.

No comments:

Subscribe (RSS)

The Leadership Journey