I've just moved hosting companies and not all functions work on this page yet.
This page is for people who know XML well, and would like a brief overview of what XSLT can do. View this page as series of slides
- Preview
During this session we will explore the following topics:
- What is XSL?
- What is the syntax?
- How much power does it offer us?
- What is its realtionship to SQL?
- Introduction
XSLT is an acronym of "Extensible Stylesheet Language Transformations". XSLT is easily confused with Cascading Style Sheets (CSS). CSS is concerned about presentation of data, while XSLT is used for creating new documents by rearranging and filtering xml data. XSLT can make multiple passes over a document.
- The Big Idea
XSL Transformations convert an XML document to another format. In the process we do fun things like rearrange the elements, prune some data, and add text before and after elements.
For example, Given an XML document like this:
<fruits> <fruit name="apple" quantity="3" /> <fruit name="pears" quantity="5" /> </fruits>
We can convert this information to an HTML table that looks like this:
<html> <body> <h1>Fruit Inventory</h1> <table border="1"> <tr><th>Name</th><th>Quantity</th></tr> <tr><td>apple</td><td>3</td></tr> <tr><td>pears</td><td>5</td></tr> </table> </body> </html>
The following XSLT file tells us how to convert the XML to something else, in this case an HTML file. It may look like greek now, but we'll learn what it means soon.
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <html> <body> <h1>Fruit Inventory</h1> <table border="1"> <tr><th>Name</th><th>Quantity</th></tr> <xsl:apply-templates select="*" /> </table> </body> </html> </xsl:template> <!-- templates --> <xsl:template match="fruit"> <tr><td> <xsl:value-of select="@name" /> </td><td> <xsl:value-of select="@quantity" /> </td></tr> </xsl:template> </xsl:stylesheet>
How do we convert to the HTML table from the XML file and an XSLT style sheet? We can do this in a few different ways. One is in programs written in something like C#, which I'll show you later. An easier way is to let your browser do it for you by adding a style sheet reference. This works for most modern browsers.
<?xml version='1.0' encoding='utf-8' ?> <?xml-stylesheet type="text/xsl" href="simpleExample.xslt"?> <fruits> <fruit name="apple" quantity="3" /> <fruit name="pears" quantity="5" /> </fruits>
If you enter http://www.fincher.org/tips/web/xslt/simpleExample2.xml into a browser window it will load the above file and make the transformation for you.
- XPath
From the w3.org definition: XPath is the result of an effort to provide a common syntax and semantics for functionality shared between XSL Transformations [XSLT] and XPointer [XPointer]. The primary purpose of XPath is to address parts of an XML [XML] document. In support of this primary purpose, it also provides basic facilities for manipulation of strings, numbers and booleans.
The return value of an XPath expression may be a node set, string, integer, or boolean value.
XPath typically operates on three types of nodes, Element nodes, attribute nodes, and text nodes.
- XPath "Location Paths"
A "location step" selects a set of nodes relative to the context node and has the general format of
Example:axis::node-test[predicate]*
child::Country[@name='US']
The "axis" is one of the following:
Axis Abbreviation Description child (empty string) All the direct children (no grandchildren, attribute nodes, or namespaces) descendant // All the children (no attribute nodes or namespaces) parent .. the immediate parent ancestor all the nodes above this one until the root is reached following-sibling all siblings after current node preceding all sibling before this node following all the nodes after this one, but not its descendents preceding all the nodes before this one (no ancestors, attributes, or namespaces) attribute @ all the attribute nodes for this node namespace namespaces nodes of the context node self . the context node itself descendant-or-self all descendents and self ancestor-or-self all ancestors and self 'node-test' typically is the name of an element (e.g., employee, salary, city)
'predicate' is an XPath expression that (ultimately) evaluates to a boolean value or oddly enough to an integer (e.g., [position() = last()]
- XPath expressions
- Node Set Functions
Examples: last(), position(), count()
- String Functions
Examples: starts-with(), contains(), string-length(),
- Boolean Functions
Examples: not, true, false
- Number Functions
Examples: number(), sum(), floor(), ceiling(), round() ,or, and, =, != ,<=, <, >=, >, mod
Note about boolean expressions. In xpath the literals "and" and "or" are used as conjunctions, not "&&" and "||".
- Node Set Functions
- Location Path
A "location path" consists of one or more location steps separated by "/". : Examples from w3.org:
-
child::para
selects thepara
element children of the context node -
child::*
selects all element children of the context node -
child::text()
selects all text node children of the context node -
child::node()
selects all the children of the context node, whatever their node type -
attribute::name
selects thename
attribute of the context node -
attribute::*
selects all the attributes of the context node -
descendant::para
selects thepara
element descendants of the context node -
ancestor::div
selects alldiv
ancestors of the context node -
ancestor-or-self::div
selects thediv
ancestors of the context node and, if the context node is adiv
element, the context node as well -
descendant-or-self::para
selects thepara
element descendants of the context node and, if the context node is apara
element, the context node as well -
self::para
selects the context node if it is apara
element, and otherwise selects nothing -
child::chapter/descendant::para
selects thepara
element descendants of thechapter
element children of the context node -
child::*/child::para
selects allpara
grandchildren of the context node -
/
selects the document root (which is always the parent of the document element) -
/descendant::para
selects all thepara
elements in the same document as the context node -
/descendant::olist/child::item
selects all theitem
elements that have anolist
parent and that are in the same document as the context node -
child::para[position()=1]
selects the firstpara
child of the context node -
child::para[position()=last()]
selects the lastpara
child of the context node -
child::para[position()=last()-1]
selects the last but onepara
child of the context node -
child::para[position()>1]
selects all thepara
children of the context node other than the firstpara
child of the context node -
following-sibling::chapter[position()=1]
selects the nextchapter
sibling of the context node -
preceding-sibling::chapter[position()=1]
selects the previouschapter
sibling of the context node -
/descendant::figure[position()=42]
selects the forty-secondfigure
element in the document -
/child::doc/child::chapter[position()=5]/child::section[position()=2]
selects the secondsection
of the fifthchapter
of thedoc
document element -
child::para[attribute::type="warning"]
selects allpara
children of the context node that have atype
attribute with valuewarning
-
child::para[attribute::type='warning'][position()=5]
selects the fifthpara
child of the context node that has atype
attribute with valuewarning
-
child::para[position()=5][attribute::type="warning"]
selects the fifthpara
child of the context node if that child has atype
attribute with valuewarning
-
child::chapter[child::title='Introduction']
selects thechapter
children of the context node that have one or moretitle
children with string-value equal toIntroduction
-
child::chapter[child::title]
selects thechapter
children of the context node that have one or moretitle
children -
child::*[self::chapter or self::appendix]
selects thechapter
andappendix
children of the context node -
child::*[self::chapter or self::appendix][position()=last()]
selects the lastchapter
orappendix
child of the context node
-
- Templates
Using XSLT is primary composed of writing "Templates" and then applying them. A template has the general form of:
Example:<xsl:template match = pattern name = qname priority = number mode = qname> <!-- Content: (xsl:param*, template) --> </xsl:template>
<xsl:template match="title"> <br /> title <u><xsl:value-of select="." /></u> </xsl:template>
- Applying Templates
Templates are then called (much like a function) by an "apply-templates" element.
Example:<xsl:apply-templates select = node-set-expression mode = qname> <!-- Content: (xsl:sort | xsl:with-param)* --> </xsl:apply-templates>
<xsl:apply-templates select="bookquotes/book/title" />
- Book Quote Examples:
The following examples will all use the "bookquotes.xml" data file. This file contains a favorite quote from books I've read, along with information about the book.
<bookquotes> <book isbn="0201835959" type="nonfiction" date="01/06/1975"> <title>The Mythical Man-Month</title> <author>Fred Brooks</author> <quote> The programmer, like the poet, works only slightly removed from pure thought-stuff. He builds his castles in the air, from air, creating by exertion of the imagination.</quote> <page>7</page> </book> <book isbn="0140260404" type="nonfiction" date="11/01/1996"> <title>The Road Ahead</title> <author>Bill Gates</author> <quote>"Success is a lousy teacher."</quote> </book> <book isbn="068483068X" type="fiction" date="01/01/1936"> <title>Gone with the Wind</title> <author>Margaret Mitchell</author> <quote>"Never pass up new experiences [Scarlett], They enrich the mind." - Rhett Butler</quote> <quote>"Southerners can never resist a losing cause." - Rhett Butler</quote> <quote>"But, no matter what sights they [the defeated Southern aristocracy] had seen, what menial tasks they had done and would have to do, they remained ladies and gentlemen, royalty in exile..."</quote> </book> </bookquotes>
A simple xsl file bookquotes1.xslt to create a simple list of the book titles
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template name='test' match="/"> <!-- write the xhtml template --> <html> <head> <title>Book Quotes - Index of Titles</title> <link href="http://fincher.org/mystyle.css" rel="stylesheet" type="text/css" /> </head> <body> <h1>Book Quotes - Index of Titles</h1> <xsl:apply-templates select="bookquotes/book/title" /> <!-- this will search for templates --> </body> </html> </xsl:template> <!-- templates --> <xsl:template match="title"> <!-- 'value-of select="."' will select the text between the xml tags for the current node --> <br /> title <u><xsl:value-of select="." /></u> </xsl:template> </xsl:stylesheet>
Applying the above stylesheet to our xml datafile results in the following transformation.
- Using xsl:variables to avoid repeating data
I hate to have the same text twice in a file, like in the title and h1 header, so lets use the xslt:variable element and only define it once, so it won't get out of sync.
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:variable name="title">Book Quotes - Index of Titles</xsl:variable> <xsl:template name='test' match="/"> <html> <head> <title><xsl:value-of select="$title"/></title> <link href="http://fincher.org/mystyle.css" rel="stylesheet" type="text/css" /> </head> <body> <h1><xsl:value-of select="$title"/></h1> <xsl:apply-templates select="bookquotes/book/title" /> </body> </html> </xsl:template> <!-- templates --> <xsl:template match="title"> <br /> title: <u><xsl:value-of select="." /></u> </xsl:template> </xsl:stylesheet>
Applying the above stylesheet we get this transformation.
- Print an attribute
Lets write a small table and extract an attribute.
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:variable name="title">Book Quotes - Index of Titles</xsl:variable> <xsl:template name='test' match="/"> <html> <head> <title><xsl:value-of select="$title"/></title> <link href="http://fincher.org/mystyle.css" rel="stylesheet" type="text/css" /> </head> <body> <h1><xsl:value-of select="$title"/></h1> <table border='1'> <tr><th>Title </th><th>ISBN </th></tr> <xsl:apply-templates select="bookquotes/book" /> </table> </body> </html> </xsl:template> <!-- templates --> <xsl:template match="book"> <tr> <td><xsl:value-of select="title" /></td> <!-- to get the value of an attribute, use the "@" character --> <td><xsl:value-of select="@isbn" /></td> </tr> </xsl:template> </xsl:stylesheet>
Applying the above stylesheet we get this transformation.
- Using values as attribute values
Use an attribute value inside another attribute. We use the a special syntax called 'Attribute Value Templates' to get the incoming attribute written to an outgoing attribute "{@isbn}"
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:variable name="title">Book Quotes - Index of Titles</xsl:variable> <xsl:template name='test' match="/"> <html> <head> <title><xsl:value-of select="$title"/></title> <link href="http://fincher.org/mystyle.css" rel="stylesheet" type="text/css" /> </head> <body> <h1><xsl:value-of select="$title"/></h1> <table border='1'> <tr><th>Title </th><th>ISBN </th></tr> <xsl:apply-templates select="bookquotes/book" /> </table> </body> </html> </xsl:template> <!-- templates --> <xsl:template match="book"> <tr> <td><xsl:value-of select="title" /></td> <!-- to get the value of an attribute, use the "@" character --> <td> <a href="http://www.amazon.com/exec/obidos/ASIN/{@isbn}">See at Amazon</a> </td> </tr> </xsl:template> </xsl:stylesheet>
Applying the above stylesheet we get this transformation.
Note: This replaces the more verbose method of:
<input type="checkbox" > <xsl:attribute name="name"> <xsl:value-of select="@name"/> </xsl:attribute> </input>
- Miscellanous expressions.
XPath gives us many ways to query a DOM object and select only nodes that match certain criteria. Its functionality and SQL have some interesting overlaps.
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:variable name="title">Book Quotes - Index of Titles</xsl:variable> <xsl:template name='test' match="/"> <html> <head> <title><xsl:value-of select="$title"/></title> <link href="http://fincher.org/mystyle.css" rel="stylesheet" type="text/css" /> </head> <body> <h1><xsl:value-of select="$title"/></h1> <br />The number of books in this file is <xsl:value-of select="count(bookquotes/book)" /> <br />Number of nonfiction books in this file is: <xsl:value-of select="count(bookquotes/book[@type='nonfiction'])" /> <br /> ** Title(s) : <xsl:apply-templates select="/bookquotes/book[@type='nonfiction']/title" /> <br />Number of books with more than one quote: <xsl:value-of select="count(bookquotes/book[count(quote) > 1])" /> <br /> ** Title(s) : <xsl:apply-templates select="/bookquotes/book[count(quote) > 1]/title" /> <br />Number of books with only one quote: <xsl:value-of select="count(bookquotes/book[count(quote) = 1])" /> <br /> ** Title(s) : <xsl:apply-templates select="/bookquotes/book[count(quote) = 1]/title" /> </body> </html> </xsl:template> <xsl:template match="title"> <u><xsl:value-of select="." /></u> , </xsl:template> </xsl:stylesheet>
Applying the above stylesheet we get this transformation.
- Tiny stylesheet to print sorted attributes of the first element as a table
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- style sheet to write the attributes of the first element as a table --> <xsl:template name='test' match="/"> <!-- write xhtml body shell --> <html> <head> <title><xsl:value-of select="name(*)"/></title> </head> <body> <h1 style="text-align: center;"><xsl:value-of select="name(*)"/></h1> <xsl:apply-templates select="*/*" /> </body> </html> </xsl:template> <!-- loop over attributes and write in html table --> <xsl:template match="*"> <table border='1'> <tr><th>Attribute Name</th><th>Attribute Value</th></tr> <xsl:apply-templates select="attribute::*" > <xsl:sort select="name(.)" order="descending" /> </xsl:apply-templates> </table> </xsl:template> <xsl:template match="attribute::*" > <tr> <td> <xsl:value-of select="name(.)" /></td> <td><xsl:value-of select="." /></td> </tr> </xsl:template> </xsl:stylesheet>
Applying the above stylesheet we get this transformation.
- Conditional Processing using xsl:if.
We can place commas behind each attribute except the last one. This example also shows the use of the "xsl:for-each" element and the "xsl:text" element.
<xsl:for-each select="Response"> <xsl:value-of select="@name"/> <xsl:value-of select="@*"/> <xsl:if test="position() != last()"> <xsl:text> ,</xsl:text> </xsl:if> </xsl:for-each>
How to include html text from one file into another using xslt.
This first file will include the second file, 'Footer.xslt' just above the closing body tag
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:include href="Footer.xsl" /> <!-- import the 'Footer.xsl' file --> <html> <body> <xsl:apply-templates select="Stuff" /> ... ... <!-- now lets grab the contents of the Footer.xsl file --> <xsl:call-template name="footer"/> </body> </html>
'Footer.xsl' should look like the following:
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template name="footer"> <hr />Copyright 2002 Fincher Enterprises </xsl:template> </xsl:stylesheet>
Using xsl:if to write default text, if no nodes found
<xsl:template match="SurveyDescriptor[@status='active']"> <tr> <td><xsl:value-of select="@name"/> </td> <td> <xsl:if test="count(ScreenerQuestion) = 0"> <!-- write "(None)" if no ScreenerQuestion children exist --> (None) </xsl:if> <xsl:for-each select="ScreenerQuestion"> <xsl:value-of select="@name"/> ( <xsl:for-each select="Response"> <xsl:value-of select="@name"/> <xsl:value-of select="@*"/> <xsl:if test="position() != last()"> <xsl:text> ,</xsl:text> </xsl:if> </xsl:for-each> ) <br /> </xsl:for-each> </td> </tr> </xsl:template>
<xsl:if test='text() != "-- SelectOne --" and text() != "-- refuse --"'> ... </xsl:if>
- Sorting
Elements in the tree can be easily sorted
<xsl:apply-templates select="Surveys/Survey"> <xsl:sort select="@priority" order="descending" data-type="number"/> </xsl:apply-templates>
- Formatting Numbers
numbers can be operated on and formated for output. The following takes the 'total' attribute and divides it by the 'target' attribute. The '0%' multiplies by 100 and puts the '%' character behind it.
<xsl:value-of select="format-number((@total div @target),'0%')"/>
- using the sum() function
The nodeset returned by the expression is turned into numbers and then summed.
<xsl:value-of select="sum(Surveys/Survey/cellName/@target) - sum(Surveys/Survey/cellName/@total)"/> <xsl:value-of select="sum(Surveys/Survey/cellName/@total)"/> <xsl:value-of select="sum(Surveys/Survey/cellName/@target)"/> <xsl:value-of select="format-number(sum(Surveys/Survey/cellName/@total) div sum(Surveys/Survey/cellName/@target), '0%')"/>
- To write characters with &s and other difficult characters
Use the 'disable-output-escaping="yes"' attribute
<xsl:text disable-output-escaping="yes"> </xsl:text>
- Bonus Example of Creating Slides
This is the xsl for creating the "Slides" view of this information
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template name='test' match="/"> <!-- write the xhtml template --> <html> <head> <title>KnowledgeBase/Web/XSLT</title> <link href="http://www.fincher.org/mystyle.css" rel="stylesheet" type="text/css" /> <meta name="description" content="XSLT" /> <meta name="keywords" content="XSLT" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <h1 style="text-align: center">XSLT Notes Page <xsl:value-of select="$page" /></h1> <hr /> | <a href="http://fincher.org/cgi-bin/transform.sh?xmlfile=index.xml&xsltfile=generic.xslt&name=page&value={$page - 1}"> < Previous</a> | <xsl:apply-templates mode="i" select="ol/li" /> <a href="http://fincher.org/cgi-bin/transform.sh?xmlfile=index.xml&xsltfile=generic.xslt&name=page&value={$page+1}">Next > </a> | <hr /> <ol> <li value="{$page}"> <xsl:apply-templates mode="x" select="ol/li[position() = $page]" /> </li> </ol> <hr /> | <a href="http://fincher.org/cgi-bin/transform.sh?xmlfile=index.xml&xsltfile=generic.xslt&name=page&value={$page - 1}"> < Previous</a> | <xsl:apply-templates mode="i" select="ol/li" /> <a href="http://fincher.org/cgi-bin/transform.sh?xmlfile=index.xml&xsltfile=generic.xslt&name=page&value={$page+1}">Next > </a> | <hr /> </body> </html> </xsl:template> <!-- templates --> <xsl:template mode="x" match="@*|node()" > <xsl:copy-of select="@*|node()" /> </xsl:template> <xsl:template mode="i" match="ol/li" > <xsl:if test="position() != $page"> <a href="http://fincher.org/cgi-bin/transform.sh?xmlfile=index.xml&xsltfile=generic.xslt&name=page&value={position()}" title="{text()}"> <xsl:value-of select="position()" /> </a> </xsl:if> <xsl:if test="position() = $page"> <b> <xsl:value-of select="position()" /> </b> </xsl:if> | </xsl:template> </xsl:stylesheet>
- Get XML documents from SQL server
SQL Server 2000 has a wacky format to retrieve XML documents. Below is an example:
SELECT distinct 1 as Tag, NULL as Parent, surveyName as [Survey!1!name], NULL as [cellName!2!name], NULL as [cellName!2!total], NULL as [cellName!2!target] FROM surveyDirectorQuotas UNION ALL SELECT distinct 2 , 1, surveyName, cellName, total, target FROM surveyDirectorQuotas ORDER BY [Survey!1!name] , [cellName!2!name] FOR XML EXPLICIT
This returns an XML document like the following:
<Surveys> <Survey name="Beer"> <cellName name="MatureEducatedMen" total="10" target="10" /> <cellName name="MatureEducatedWomen" total="3" target="10" /> </Survey> <Survey name="Cars"> <cellName name="OtherEducatedMen" total="3" target="10" /> <cellName name="OtherEducatedWomen" total="10" target="10" /> </Survey> <Survey name="Grocery"> <cellName name="EveryoneOver16" total="3" target="20" /> </Survey> <Survey name="GroceryFull"> <cellName name="EveryoneOver16" total="20" target="20" /> </Survey> </Surveys>
- Command Line Transformations
The NT command to do transformations with xalan
java -classpath (directory)/xalan.jar org.apache.xalan.xslt.Process -IN bookquotes.xml -XSL bookquotes1.xslt -PARAM name value
Microsoft provides a command line tool for xsl transformations called msxsl.exe
- Browser Based Transformations
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml-stylesheet type="text/xsl" href="abook.xslt"?> <catalog> <keyword>Peter+Rabbit</keyword> <product_group>Books</product_group> <product> <ranking>1</ranking> <title>Beatrix Potter : The Complete Tales : The 23 Original Peter Rabbit Books & 4 Unpublished Works</title> <asin>0723244049</asin> <author>Potter, Beatrix</author> <image>http://images.amazon.com/images/P/0723244049.01.MZZZZZZZ.jpg</image> <release_date>19971000</release_date> <binding>Hardcover</binding> <availability> </availability> <tagged_url>http://www.amazon.com:80/exec/obidos/redirect?tag=phonelistscom&creative=9441&camp=1793&link_code=xml&path=ASIN/0723244049</tagged_url> </product>
This works really well, if you know all the browsers hitting your site can do client side transformations.
- Server Side Transformation
The link to your xslt transformed page can point to a cgi program that does the transformation on the server. Here's a bit of perl cgi code that invokes Xalan on an Apache server to transform for us.
$xmlfile = $in{xmlfile}; $xsltfile = $in{xsltfile}; $name = $in{name}; $value = $in{value}; $cmd = "/usr/local/jdk/bin/java -classpath /big/dom/xfincher/www/xalan.jar org.apache.xalan.xslt.Process -IN ${xmlfile} -XSL ${xsltfile} -PARAM ${name} ${value}"; open(RESULTSET, $cmd." | ") || die "cannot do a xslt transform"; while($line = <RESULTSET>) { chomp($line); print "$line\n"; } close(RESULTSET);
This is nice, but a heavy hit on the server cpu.
- Best of both worlds
If the browser can transform, let it do it; otherwise do server-side transformation.
<script> agt=navigator.userAgent.toLowerCase(); IE6exist = agt.indexOf("msie 6.0"); if (IE6exist > -1) {location = "abook.xml"} </script> <!--#include virtual="cgi-bin/books.sh?xmlfile=/big/dom/www/McGregorsGarden/abook.xml&xsltfile=/big/dom/www/McGregorsGarden/abook.xslt" -->
See for yourself at www.McGregorsGarden.com
- Cocoon is a server side xsl transformer managed by the apache group.
- .Net transformation in c sharp
You can reference csharp code from your .Net pages
public class SurveyStatus : System.Web.UI.Page { private void Page_Load(object sender, System.EventArgs e) { GetSurveyDescriptorXMLService service = new GetSurveyDescriptorXMLService(); XmlDocument xmlDocument = service.GetAllSurveyDescriptorsAsXMLDoc(); string output = Util.WriteXMLViaXSL(xmlDocument, "w:/SurveyDirector/data/Xsl/SurveyDescriptorStatus.xsl"); Response.Write(output); } }
This will reference this csharp code:
public static string WriteXMLViaXSL(XmlDocument xmlDocument, string styleSheetFileName) { //read an xml doc, twist it with an xsl file and return as string XslTransform xslTransform = new XslTransform(); xslTransform.Load(styleSheetFileName); return WriteXMLViaXSL(xmlDocument, xslTransform); } public static string WriteXMLViaXSL(XmlDocument xmlDocument, XslTransform xslTransform) { //read an xml doc, twist it with an xsl file and return as string StringWriter stringWriter = new StringWriter(); XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter); xmlTextWriter.Formatting = Formatting.Indented; xslTransform.Transform(xmlDocument, null, xmlTextWriter); xmlTextWriter.Flush(); return stringWriter.ToString(); }
- Addendum April 2004
Example of using stylesheets for format an xml file into a friendly HTML page in IE6
XSLT file:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" /> <xsl:template match="/"> <html> <title>Test Cases for 'BestPossibleSurvey' Calculations</title> <body> <h1 style='text-align: center'>Test Cases for 'BestPossibleSurvey' Calculations</h1> <table border='2'> <tr><th>Name</th><th>Description</th></tr> <xsl:apply-templates select="//BestPossibleSurvey" /> </table> </body> </html> </xsl:template> <xsl:template match="BestPossibleSurvey"> <tr> <td><xsl:value-of select="@name" /></td> <td><xsl:value-of select="@desc" /></td> </tr> </xsl:template> </xsl:stylesheet>
XML file:
<?xml version="1.0" encoding="utf-8" ?> <?xml-stylesheet type="text/xsl" href="BestPossibleSurvey.xslt"?> <Tests> <BestPossibleSurvey name="BPS01" desc="The respondent has seen no keyquestions before." respondent="Respondents\\KQ01.xml" surveyStatus="SurveyStatus\\CASE02.xml" result="MOONMAND" /> <BestPossibleSurvey name="BPS02a" desc="The respondent checked yes to all keyquestions. Same as BPS02 except the userID is changed, so the survey selection is also changed. This tests to make sure that selections are random." respondent="Respondents\\BPS02a.xml" surveyStatus="SurveyStatus\\CASE02.xml" result="MOONMANF,MOONMANH,MOONMANJ,MOONMANI,MOONMANB,MOONMANA,MOONMANC,MOONMANE,MOONMAND" /> <BestPossibleSurvey name="BPS03" desc="The respondent checked yes to all keyquestions. Same as BPS02a except the group's PriorityAlgorithm is changed to assigned, so the survey selection is also changed." respondent="Respondents\\BPS02a.xml" surveyStatus="SurveyStatus\\CASE02.xml" group="Tests\\Groups\\BPS03-Baseln.xml" result="MOONMANA" /> </Tests>
- Review
During this session we will explore the following topics:
- What is XSL? - It transforms documents on browser or server.
- What is the syntax? Kinda wacky, but knowable.
- How much power does it offer us? A great amount of filtering and manupilating data.
- What is its realtionship to SQL? Similiar in function in many ways.
- My favorite links:
- Definition of www.w3.org/TR/xslt
- Definition of www.w3.org/TR/xpath
- www.xslt.com/
- www.topxml.com/xsl/
- http://www.devguru.com
- Recommended Books: