XML and XSLT transformation in ASP.NET MVC - HtmlHelper.RenderXml extensions

In ASP.NET we had Xml control. Let's try providing functionality close to it. How about extension class with following methods:
public static class RenderXmlExtensions
{
  public static void RenderXml(this HtmlHelper htmlHelper, XmlDocument xmlDocument, XslCompiledTransform transform) { ... }
  public static void RenderXml(this HtmlHelper htmlHelper, XmlDocument xmlDocument, XslCompiledTransform transform, XsltArgumentList transformArgumentList) { ... }
  public static void RenderXml(this HtmlHelper htmlHelper, XmlDocument xmlDocument, string transformSource) { ... }
  public static void RenderXml(this HtmlHelper htmlHelper, XmlDocument xmlDocument, string transformSource, XsltArgumentList transformArgumentList) { ... }
  public static void RenderXml(this HtmlHelper htmlHelper, XPathNavigator xpathNavigator, XslCompiledTransform transform) { ... }
  public static void RenderXml(this HtmlHelper htmlHelper, XPathNavigator xpathNavigator, XslCompiledTransform transform, XsltArgumentList transformArgumentList) { ... }
  public static void RenderXml(this HtmlHelper htmlHelper, XPathNavigator xpathNavigator, string transformSource) { ... }
  public static void RenderXml(this HtmlHelper htmlHelper, XPathNavigator xpathNavigator, string transformSource, XsltArgumentList transformArgumentList) { ... }
  public static void RenderXml(this HtmlHelper htmlHelper, string documentSource, XslCompiledTransform transform) { ... }
  public static void RenderXml(this HtmlHelper htmlHelper, string documentSource, XslCompiledTransform transform, XsltArgumentList transformArgumentList) { ... }
  public static void RenderXml(this HtmlHelper htmlHelper, string documentSource, string transformSource) { ... }
  public static void RenderXml(this HtmlHelper htmlHelper, string documentSource, string transformSource, XsltArgumentList transformArgumentList) { ... }
}

Ok, that's a lot of methods. But don't worry, all of them will call single internal method, which will perform actual rendering:
private static void RenderXmlInternal(HtmlHelper htmlHelper, XmlDocument xmlDocument, XPathNavigator xpathNavigator, string documentSource, XslCompiledTransform transform, string transformSource, XsltArgumentList transformArgumentList)
{
  XPathDocument xpathDocument = null;
  //Checking if we have been given XmlDocument or XPathNavigator directly,
  //or do we have path for document
  if ((xmlDocument == null) && (xpathNavigator == null) &&
     (!String.IsNullOrEmpty(documentSource) && (documentSource.Trim().Length != 0)))
  {
    //Checking if path is absolute or relative
    if (!Path.IsPathRooted(documentSource))
      //Mapping the relative path
      documentSource = htmlHelper.ViewContext.HttpContext.Server.MapPath(documentSource);

    //Loading XML from file into XPathDocument
    using (FileStream documentStream = new FileStream(documentSource,
           FileMode.Open, FileAccess.Read, FileShare.Read))
    {
      XmlTextReader documentReader = new XmlTextReader(documentStream);
      xpathDocument = new XPathDocument(documentReader);
    }
  }

  //Checking if we have been given XslCompiledTransform directly,
  //or do we have path for transform
  if ((transform == null) &&
(!String.IsNullOrEmpty(transformSource) && (transformSource.Trim().Length != 0)))
  {
    //Checking if path is absolute or relative
    if (!Path.IsPathRooted(transformSource))
      //Mapping the relative path
      transformSource = htmlHelper.ViewContext.HttpContext.Server.MapPath(transformSource);

    //Loading XSLT from file into XslCompiledTransform
    using (FileStream transformStream = new FileStream(transformSource,
           FileMode.Open, FileAccess.Read, FileShare.Read))
    {
      XmlTextReader tranformReader = new XmlTextReader(transformStream);
      transform = new XslCompiledTransform();
      transform.Load(tranformReader);
    }
  }

  //Checking if we have XML in any form
  if (((xmlDocument != null) || (xpathDocument != null)) || (xpathNavigator != null))
  {
    //Checking if we have XSLT
    if (transform == null)
      //If not, let's use transparent one
      transform = _transparentTransform;

    //Perform transformation based on form in which we have our XML
    if (xmlDocument != null)
      transform.Transform((IXPathNavigable)xmlDocument, transformArgumentList,
                          htmlHelper.ViewContext.HttpContext.Response.Output);
    else if (xpathNavigator != null)
      transform.Transform(xpathNavigator, transformArgumentList,
                          htmlHelper.ViewContext.HttpContext.Response.Output);
    else
      transform.Transform((IXPathNavigable)xpathDocument, transformArgumentList,
                          htmlHelper.ViewContext.HttpContext.Response.Output);
  }
}

Isn't that simple? All we have to do now is adding our namespace in web.config
<configuration>
  ...
  <system.web>
    ...
    <pages>
      ...
      <namespaces>
        ...
        <add namespace="Lib.Web.Mvc.Html"/>
      </namespaces>
    </pages>
    ...
  </system.web>
  ...
</configuration>

prepare controller action, which will pass our XML to view
public ActionResult RenderXml()
{
  XmlDocument cdCatalogDocument = new XmlDocument();
  cdCatalogDocument.Load(Server.MapPath("~/App_Data/CDCatalog.xml"));
  return View(cdCatalogDocument);
}

call our extension method in the view
<asp:Content ID="cContent" ContentPlaceHolderID="cphContent" runat="server">
  <% Html.RenderXml((System.Xml.XmlDocument)Model, "~/Xslt/CDCatalog.xsl"); %>
</asp:Content>

and we can see the results.

The extension class can be found here (you can also download sample application from here). I will probably write one more post about this subject, with a little bit different approach.