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:
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.
public static class RenderXmlExtensionsOk, that's a lot of methods. But don't worry, all of them will call single internal method, which will perform actual rendering:
{
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) { ... }
}
private static void RenderXmlInternal(HtmlHelper htmlHelper, XmlDocument xmlDocument, XPathNavigator xpathNavigator, string documentSource, XslCompiledTransform transform, string transformSource, XsltArgumentList transformArgumentList)Isn't that simple? All we have to do now is adding our namespace in web.config
{
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);
}
}
<configuration>prepare controller action, which will pass our XML to view
...
<system.web>
...
<pages>
...
<namespaces>
...
<add namespace="Lib.Web.Mvc.Html"/>
</namespaces>
</pages>
...
</system.web>
...
</configuration>
public ActionResult RenderXml()call our extension method in the view
{
XmlDocument cdCatalogDocument = new XmlDocument();
cdCatalogDocument.Load(Server.MapPath("~/App_Data/CDCatalog.xml"));
return View(cdCatalogDocument);
}
<asp:Content ID="cContent" ContentPlaceHolderID="cphContent" runat="server">and we can see the results.
<% Html.RenderXml((System.Xml.XmlDocument)Model, "~/Xslt/CDCatalog.xsl"); %>
</asp:Content>
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.