XSLT to display an XML document as HTML

I had a quick and dirty project to take some XML that was stored in our database and display it on a web page in an existing site. Normally I’d have a fairly large amount of client side tooling to perform this job, but the site was entirely based in WebForms and I really did not want to add new dependencies to the project. It became clear that the quick and dirty version of this involved using the Xml web control and binding the XML and XSL to the control. There are a bunch of articles on MSDN that purport to show you how to do this that end up being tedious.

The reality is that you can add this to your ASPX page.

<asp:Xml ID="XmlDisplay" runat="server" />

Then something like this to your codebehind

XmlDisplay.DocumentContent = MyXmlDocOrElement.ToString(); 
XmlDisplay.TransformSource = HttpContext.Current.Server.MapPath(@"../PathToMyXslt/MyXslt.xsl"); 

And you’ve got your XML on your page.

Then the only thing that is left is the XSLT to make your XML look pretty on the page. I actually had very little XSLT experience and took a few wrong turns trying to cook something up that would do this that involved using recursion and printing out all the values using individual XSL tags that I generated. This ended up being stupidly complex, but despite my ignorance I had a sense that I was doing something wrong so I took a step back and a co-worker and I talked for a bit and he mentioned that he thought XSLT just sort of did what I was trying to do with code. Well, turns out he was right. Now, to be fair, the XML I needed to display has no attributes, so this is really just printing out element names and values, but with a little work you could also find attributes fairly easily.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
	<xsl:output method="html" version="1.0" encoding="ISO-8859-1" indent="yes" />
	<xsl:template match="/">
		<div class="root">
			<xsl:for-each select="//*">
						<xsl:when test="not(text())">
							<div class="col-name{count(ancestor::*)} col-empty-value" title="{name()}">
								<xsl:value-of select="name()"/>
							<div class="col-name{count(ancestor::*)}" title="{name()}">
								<xsl:value-of select="name()"/>
							<div class="col-value{count(ancestor::*)}" title="{text()}">
								<xsl:value-of select="text()"/>

This XSL will take any XML that is formatted as only elements and element values and print it out as a series of DIVs.

The meat of making this a decent looking display is the ability to apply dynamic CSS class names to the HTML elements you render from the XSLT as you go down the tree of XML. As the XSLT iterates over the various elements using xsl:for-each you can use count(ancestor::*) to apply a numeric value to your class name indicating the depth.

You could also probably cook up a table structure using this same method.

Leave a Reply

Your email address will not be published. Required fields are marked *