1

I have a xslt file, myxslt.xslt, that contains an import, that looks a bit like this:

<?xml version="1.0" encoding="utf-8"?>    
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:import href="someOtherXsltFile.xslt"/>
  <!--Do some transformations -->  
</xsl:stylesheet>

I am trying to import these files into my C# application by using the assembly:

Assembly assembly = Assembly.GetExecutingAssembly();

        using (Stream xsltStream = assembly.GetManifestResourceStream(mynamespace.myxslt.xslt))
        {
            using (XmlReader xsltReader = XmlReader.Create(xsltStream))
            {
                xslt.Load(xsltReader);
            }
        }

as I saw in this answer: Adding (Embedded Resource) Schema To XmlReaderSettings Instead Of Filename?

The Stream and XmlReader load fine.

However my application throws a cannot find file exception when I try to load the xslt. The file that it cannot load is someOtherXsltFile.xslt.

Both files are loaded as an embedded resource and both are visible in the list from assembly.GetManifestResourceNames.

I would rather not change anything in the xslt files as those are standard files that came with the messages that I am trying to transform.

Is there a way to load my xslt using an import from the assembly?

Community
  • 1
  • 1
  • [This question](http://stackoverflow.com/questions/995591/how-to-resolve-xsl-includes-in-a-transformation-that-loads-xsl-from-a-string) may be relevant – stuartd Sep 26 '16 at 13:44

1 Answers1

2

Thanks to the link posted by stuartd (How to resolve XSL includes in a Transformation that loads XSL from a String?) I have managed to figure out the solution.

My import now looks like this:

        Assembly assembly = Assembly.GetExecutingAssembly();

        using (Stream xsltStream = assembly.GetManifestResourceStream(mynamespace.myxslt.xslt))
        {
            using (XmlReader xsltReader = XmlReader.Create(xsltStream))
            {
                var resolver = new MyXmlUrlResolver();
                xslt.Load(xsltReader,null,resolver);
            }
        }

And the MyXmlUrlResolver is defined as follows:

private class MyXmlUrlResolver : XmlUrlResolver
    {
        private const string basePad = "MyNamespace.mysubnamespace.";

        public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
        {
            switch (absoluteUri.Scheme)
            {
                case "file":
                    {
                        string origString = absoluteUri.OriginalString;
                        Assembly assembly = Assembly.GetExecutingAssembly();
                        // the filename starts after the last \
                        int index = origString.LastIndexOf('\\');                            
                        string filename = origString.Substring(index + 1);

                        string resourceName = basePad + filename;

                        var stream = assembly.GetManifestResourceStream(resourceName);

                        return stream;
                    }
                default:
                    {
                        return (Stream)base.GetEntity(absoluteUri, role, ofObjectToReturn);
                    }
            }
        }
    }

This loads the xslt including all of its imports.

Community
  • 1
  • 1