C# Embedded Xsl Resource Resolving
Posted: September 12, 2006 Filed under: .NET, Computers Leave a comment »I ran into a problem today developing a web app that uses XML/XSLT for the display. This particular widget is designed to run as a custom control and it compiles to a .dll, so I had to embed my XSL files. This wasn’t a problem until I tried to clean up the XSLs by dividing them into smaller pieces and using xsl:include from between them.
The problem turned out to have a quick solution that took about an hour. Write a Custom XmlResolver. Now the one on the Microsoft Website is pretty extensive if you want to learn all about it. But if you want to just drop a class file in your project you can use mine. It resolves everything relative to the namespace that you put it in, so be sure to change that to something appropriate, espeically if you have your default namespace set in Visual Studio.
Note this is quick and dirty and doesn’t do anything with credentials, which I figure is OK since you probably have permission to get to your embedded resources.
Click below to see the full code:
[csharp]
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Xsl;
using System.Reflection;
using System.IO;
namespace Brian.Samson.Xml
{
class EmbeddedResourceResolver : XmlResolver
{
private System.Net.ICredentials _credentials;
public override System.Net.ICredentials Credentials
{
set { _credentials = value; }
}
public override Uri ResolveUri(Uri baseUri, string relativeUri)
{
string escapedUri = relativeUri.Replace(‘/’, ‘.’);
if (baseUri == null)
return new Uri(escapedUri, UriKind.Relative);
else
return new Uri(stripFileName(baseUri.OriginalString) + “.” + escapedUri, UriKind.Relative);
}
public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
{
string uri = this.GetType().Namespace + “.” + absoluteUri.OriginalString;
Stream s = typeof(Common).Assembly.GetManifestResourceStream(uri);
return s;
}
/*
* Strip the filename part of a dotted-path Uri
* i.e. if you pass in “my.name.space.new.xsl” it will return “my.name.space”
* This is needed for relative uri parsing, since we lose all the slashes
*/
private string stripFileName(string dottedPath)
{
string[] parts = dottedPath.Split(new char[] { ‘.’ });
string basePath = “”;
if (parts.Length > 2)
{
string[] baseparts = new string[parts.Length - 2];
Array.ConstrainedCopy(parts, 0, baseparts, 0, parts.Length – 2);
basePath = String.Concat(baseparts);
}
return basePath;
}
}
}
[/csharp]