XSLT For A DataSet Designer XSS File
XML is being used for a lot of configuration files and to store application and system settings. It is also used extensively to define the presentation layer; Windows Presentation Foundation and Mozilla's XML User Interface Language for example. Therefore it is often useful to be able to transform XML into a more readable format for documentation.
Visual Studio 2005 uses a lot of XML files to store the DataSets and the design surface of the DataSet Designer. I am currently working on a project where I have to reconcile my DataSet with the DataSet of another developer. It is tedious to open both projects in Visual Studio and then scroll around the design surface of the DataSet Designer trying to count tables and trying to compare table adapter names. It occurred to me that I could make it easier to compare our DataSets if I used XSLT to transform one of the XML files into a list.
Of the four files associated with the DataSet, I choose the XSS file because it is fairly simple and contains all the information I needed. The XSS file stores the position of the shapes on the design surface. I wanted to use the XSD file but I had a lot of trouble with it (more on that later).
It does not require any code to do a XML transformation in ASP.NET 2.0. Just drag an XML control onto your form and set the DocumentSource and the TransformSource:
<asp:Xml ID="Xml1" DocumentSource="~/App_Data/dsData.xss" runat="server" TransformSource="~/App_Data/XSS.xsl"></asp:Xml>
Although XSLT could be compared to CSS, being sort of a style sheet for XML, you can actually write a lot of code in your XSL files so you should regard it as a specialized programming language that you need to learn. Visual Studio 2005 does a good job as a XSLT editor but it is not perfect. It will alert you to syntax errors and malformed XML tags but lacks any Intellisense. The most frustrating aspect of coding XSLT is getting your XPaths correct. I usually have to experiment for hours before I can properly reference an XML element or attribute. The XML namespace often gives me a lot of trouble. This is why I could not use the XSD file. Its XML format makes getting a XPath extremely difficult and I was unable to reference the TableAdaper element. My XSL for the XSS file gives me a count of the TableAdapters in the DataSet and then lists them in alphabetical order as a numbered list. Getting the table count and sorting the TableAdapter names is done entirely in XSLT code which demonstrates the power of XML transformation:
<?xml version="1.0" encoding="utf-8" ?> <xsl:stylesheet version="1.0" xmlns:ds="urn:schemas-microsoft-com:xml-msdatasource-layout" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" method="html" /> <xsl:template match="/"> <!-- This is an XSL template file. --> <table bgcolor="#FFFFFF" cellspacing="0" cellpadding="1"> <tr bgcolor="#000000"> <td> <font color="#FFFFFF"> <b> <!-- counter for xml elements --> <xsl:value-of select="count(ds:DiagramLayout/ds:Shapes/ds:Shape)"/> Design Table(s) </b> </font> </td> </tr> <xsl:for-each select="ds:DiagramLayout/ds:Shapes/ds:Shape"> <xsl:sort select="@ID"/> <xsl:if test="position() mod 2 = 1"> <tr bgcolor="#CCFFCC"> <td> <xsl:number value="position()"/>. <xsl:value-of select="substring-after(@ID,'DesignTable:')"/> </td> </tr> </xsl:if> <xsl:if test="position() mod 2 = 0"> <tr bgcolor="#FFFFFF"> <td> <xsl:number value="position()"/>. <xsl:value-of select="substring-after(@ID,'DesignTable:')"/> </td> </tr> </xsl:if> </xsl:for-each> </table> </xsl:template> </xsl:stylesheet>
The element count is accomplished by using the count function which requires the xpath to the element to be counted. The sorting of the XML elements is done by the XSL element xsl:sort which is selecting the ID attribute for each Shape element. I remove some text from the ID attribute using the substring-after function. The position function is used to number the elements and to alternate the HTML table row background color. The ds: prefix is required in the xpaths as a shorthand reference to the namespace and must be defined in the xsl:stylesheet element. This can be very tricky. It is usually very hard to get that right. XMLSpy can help you with that but it is very expensive.
By the way, while researching this, the XSS keyword gave me search results for Cross Site Scripting attacks using XSL. It is possible to extend the power of XSLT using JavaScript embedded into the XSL file. Therefore any web application that allows the user to upload their own XSL file will be vulnerable to Cross Site Scripting attacks. I've been learning a lot about the dangers of JavaScript snuck into user input. Attackers can use JavaScript in CSS files and send HTTP headers containing JavaScript for sneaky exploits but that is another topic.