XSLT – Extensible Style Language for Transformation Presented by: Igor Borodin Ilya Brodin Motivation Transformation of XML document – Why do we need it? Store in one format, display in another Transforming XML to XHTML and displaying in browser, for example Convert to a more useful format Make the document more compact Extracting from XML documents only the data we need The common: we are interested to get another document that looks like we specify Transformation basics For performing a transformation, we need: Input document The specification of the transformation (how to perform it, what is the input, what is the output) Transformation processor XSLT is a language for defining transformations of XML documents Transformation basics (cont.) XSLT is a declarative XML-based stylesheet language XSLT stylesheet is an XML document by itself It consists of a set of rules that match patterns in input XML document The rules declare what output should be produced when a pattern in the XML document is matched The order of the definition of rules doesn’t matter Transformation basics (cont.) Transformation processor applies the rules on an XML document, producing the output The output is a text document that may be an XML document, of course. So, XSLT transformation allows us to transform XML in any text based format. Simple example Lets examine a simple example of using XSLT to transform an XML document into an HTML table: Input document: people.xml Stylesheet: people.xsl with the rules of transformation In order to perform transformation specified by people.xsl, we have to insert the following processor instruction at the beginning of the input document: <?xml-stylesheet type="text/xsl" href="people.xsl"?> people.xml: Note the assignment of XSLT stylesheet <?xml version="1.0" ?> <?xml-stylesheet type="text/xsl" href="people.xsl"?> <PEOPLE> <PERSON> <NAME>Mark Wilson</NAME> <ADDRESS>911 Somewhere Circle, Canberra, Australia</ADDRESS> <TEL>(++612) 12345</TEL> <FAX>(++612) 12345</FAX> <EMAIL>Mark.Wilson@somewhere.com</EMAIL> </PERSON> <PERSON> <NAME>Tracey Wilson</NAME> <ADDRESS>121 Zootle Road, Cape Town, South Africa</ADDRESS> <TEL>(++2721) 531 9090</TEL> <FAX>(++2721) 531 9090</FAX> <EMAIL>Tracey.Wilson@somewhere.com</EMAIL> </PERSON> <PERSON> <NAME>Jodie Foster</NAME> <ADDRESS>30 Animal Road, New York, USA</ADDRESS> <TEL>(++1) 3000 12345</TEL> <FAX>(++1) 3000 12345</FAX> <EMAIL>Jodie.Foster@somewhere.com</EMAIL> </PERSON> <PERSON> <NAME>Lorrin Maughan</NAME> <ADDRESS>1143 Winners Lane, London, UK</ADDRESS> <TEL>(++94) 17 12345</TEL> <FAX>(++94) 17 12345</FAX> <EMAIL>Lorrin.Maughan@somewhere.com</EMAIL> </PERSON> <PERSON> <NAME>Steve Rachel</NAME> <ADDRESS>90210 Beverly Hills, California, USA</ADDRESS> <TEL>(++1) 2000 12345</TEL> <FAX>(++1) 2000 12345</FAX> <EMAIL>Steve.Rachel@somewhere.com</EMAIL></PERSON> </PEOPLE> <?xml version="1.0"?> people.xsl <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <HTML><BODY> <TABLE BORDER="2"> <TR> <TD>Name</TD> <TD>Address</TD> <TD>Tel</TD> <TD>Fax</TD> rule <TD>Email</TD> </TR> <xsl:for-each select="PEOPLE/PERSON"> <TR> <TD><xsl:value-of select="NAME"/></TD> <TD><xsl:value-of select="ADDRESS"/></TD> <TD><xsl:value-of select="TEL"/></TD> <TD><xsl:value-of select="FAX"/></TD> <TD><xsl:value-of select="EMAIL"/></TD> </TR> </xsl:for-each> </TABLE></BODY></HTML></xsl:template></xsl:stylesheet> The result (after transformation in Mozilla browser) What have we seen? Stylesheet is an XML document XSLT has its own set of tags and its own namespace Rules are being declared using <xsl:template match=”nodeset-expression”> tag node-set-expression is an XPath expression The contents of rule definition define the output of the application of the rule So, why XSLT? Simple syntax Easy to write Easy to read and understand Reusable + all the advantages of being the XML based language The stylesheet as XML document XSLT stylesheet is an XML document, so: The whole stylesheet should be well-formed, the following rule is invalid: <xsl:template match="/"> <trifle> <piffle> <flim> </piffle> </trifle> </xsl:template> Like any XML document, contains XML declaration at the top The stylesheet as XML document Its document element is <xsl:stylesheet> which contains all the template rules The XSLT namespace has the URI http://www.w3.org/1999/XSL/Transform The xsl prefix is used by the transformation processor to determine which elements are part of the stylesheet infrastructure and which are part of the output Tree representation of an XML document It is convenient to think about transformation process and output producing as about traveling on the input tree and building the output tree piece-by-piece Traveling starts from the root of the tree, and proceeds down So, we will represent XML document as a tree The same representation we met before in this course Tree representation of an XML document Moreover, as we saw in example, XSLT uses XPath to access or refer to parts of an XML document <xsl:for-each select="PEOPLE/PERSON"> For understanding and writing XPATH expressions, it is convenient to think of an XML document as a tree So, let’s briefly recall what the tree representation of an XML document is: Tree representation of an XML document There are 7 kinds of nodes: Element: may contain another elements Attribute: leaf node Text: leaf node. One element can have several text child nodes Comment Processing instruction Namespace Root: an abstract point above the document element Tree representation of an XML document The following document contains all these types of nodes: <?xml version="1.0"?> <!-- Dee-licious! --> <sandwich xmlns="http://www.food.org/ns"> <ingredient type="grape">jelly</ingredient> <ingredient> <?knife spread thickly?> peanut-butter </ingredient> <ingredient> bread <!-- white bread, preferably --> </ingredient> </sandwich> Tree representation of an XML document Here is its tree representation: Expressing Structure with Templates The rule in the transformation is an XML element called <xsl:template> whose contents are the elements and data that will form the result subtree. Here is an example of template rule: <xsl:template match="/"> <html> <head> <title>My first template rule</title> </head> <body> <h1>Hello, world!</h1> </body> </html> </xsl:template> Expressing Structure with Templates The output is an HTML document: <html> <head> <title>My first template rule</title> </head> <body> <h1>Hello, world!</h1> </body> </html> But we can consider the output as a tree. This tree was actually built by the rule, node by node Expressing Structure with Templates Notice the match attribute in the <xsl:template> element. This attribute selects the appropriate level of a source tree. In the example, the attribute selects the root node. This is where traveling on the input tree (transformation) starts, and therefore, our example rule will be the first rule executed Since the rule doesn't allow processing to continue past the root node (there are no references to the children of this node), it effectively blocks all other rules. The transformation not only begins with this rule, but ends here as well Expressing Structure with Templates There are special elements that transmit the processing to another levels of the input tree, i.e. another rules will continue the constructing of the result tree. In the example we saw some of them: <xsl:for-each select=“node-set-expression”> <xsl:value-of select=“node-set-expression”> There are more, will be described later Selecting nodes XSLT needs to be able to move through the document tree, to select nodes or data, to describe the location of a node or a group of nodes somewhere in a document These skills are provided by XPath XPath calls the description of the location a location path The structure of a location path: Axis – describes the direction to travel Node test – specifies what kinds of nodes are applicable Set of optional Boolean predicates – winnowing down the candidates even further XPath- node axes XPath- node tests XPath- location path examples XPath- predicate examples XPath- location path shortcuts Match patterns Location paths most often used in match attributes of <xsl:template> elements (we will call them match patterns) But there is a little difference from the generic case: Only descending or self-referential axes may be used Axes like parent and preceding make things way too complicated and could possibly set up infinite loops Match patterns - examples <xsl:template match="aphorism"> . . . </xsl:template> <xsl:template match=“quote | aphorism”> . . . </xsl:template> Will be called each time element <aphorism> is found Will be called each time elements <aphorism> or <quote> are found <xsl:template match=“category/quote”> . . . </xsl:template> Will be called each time element <quote> that live inside <category> is found Match patterns - examples <xsl:template match=“quote[@id = ‘4’]"> . . . </xsl:template> <xsl:template match=“@type”> . . . </xsl:template> Will be called each time <quote> having attribute id with value 4 is found Will be called each time attribute node type is found <xsl:template match=“quote[source/text(‘Greg Travis’)]”> . . . </xsl:template> Will be called each time element <quote> whose source is Greg Travis is found Resolving conflicts among rules It's possible for more than one rule to match a node XSLT processor selects the best match Here are the rules of precedence: If the pattern contains multiple alternatives separated by | , each alternative is treated with equal importance, as though there were a separate rule for each A specific pattern has higher priority than a pattern that contains general information. For example, the pattern quotelist/quote/body is more specific than body, and takes precedence Resolving conflicts among rules The rules of precedence (continued): A pattern that relies on a wildcard is more general and therefore has lower priority than a specific pattern. The pattern stuff/cruft defeats the wildcard pattern stuff/* A pattern with a successful test expression in square brackets ([]) overrides a pattern with no test expression but that is otherwise identical. So bobo[@role="clown"] is better than bobo Other information, such as position in the stylesheet, may be used to pare down the set if there is still more than one rule remaining Resolving conflicts among rules The <xsl:template> element has an optional priority attribute that can be set to give it precedence over other rules and override the process of determination The value must be a real number (i.e., it must have a decimal point) between 1.0 and -1.0, with a default of 0 A larger number overrides a smaller number Transformation process Transformation starts at the root of the document, “/” in XPath It maintains the stack of rules For each node it meets, it calls the template rule that match this node What to do if there is no rule defined? Next slide answers… The rule produces the output that it specifies. It can call another template, putting it at the top of the stack If the stack becomes empty, transformation stops! We have seen the example of such situation Default rules What happens if transformation process finds a node in the tree and there is no rule defined that match that node? There are default (built-in) template rules to allow recursive processing to continue in the absence of a successful pattern match by an explicit template rule in the stylesheet Each node type has a built-in rule that matches it So, there is always rule for any node Default rules have the lowest priority, thus defined rules override them Default rules Root or any element: <xsl:template match="*|/"> <xsl:applytemplates/> </xsl:template> <xsl:apply-templates/> instruction calls the templates that match immediate children of the current node (puts them on stack) We found a problem – it doesn’t calls the templates of attribute child nodes Text and attribute nodes: <xsl:template match="text()|@*"> <xsl:value-of select="."/> </xsl:template> <xsl:value-of select="."/> instruction copies the value of the matched node to the output (text in this case). Formal definition of value – in next slides. Default rules Processing instruction or comment: <xsl:template match="processinginstruction()|comment()"/> Takes no action – filters that nodes out Namespace nodes: The built-in template rule for namespace nodes is also to do nothing There is no pattern that can match a namespace node So, the built-in template rule is the only template rule that is applied for namespace nodes Boolean conditions What if we interested to produce the output under some conditions? There are several ways to do so, each relies on the result of certain XPath expression First, XPath expression can evaluate to the following types of values: Boolean (true or false) Node set Number String Result tree fragment (a mixture of nodes in a tree structure that aren't well-formed XML) Boolean conditions Each of the returned types can be converted to a Boolean value according to the following rules: Boolean conditions So, lets return to our question: what if we interested to produce the output under some conditions? One way: we can write several rules, each one will be called when our condition is satisfied For example: <xsl:template match="category[@type=‘humor’]"> . . . </xsl:template> <xsl:template match="category[@type=‘philosophy’]"> . . . </xsl:template> Boolean conditions Another way – to use XSLT special elements for conditional processing <xsl:if test = “boolean-expression”> . . . </xsl:if> <xsl:template match="category"> <xsl:if test="@type='humor'"> For example: . . . </xsl:if> </xsl:template> <xsl:template match="*"> <xsl:if test="child::*"> I have children. </xsl:if> </xsl:template> <xsl:if test="@type='philosophy'"> . . . </xsl:if> </xsl:template> Boolean conditions <xsl:template match="category[@type=‘humor’]"> Hello, world! </xsl:template> <xsl:template match="category"> <xsl:if test="@type='humor'"> Hello, world! </xsl:if> </xsl:template> Let’s define stylesheet with one of these rules only. Will the output be the same? (the . . . is the same text) No! Can you explain why? Boolean conditions Another useful element is <xsl:choose> Each <xsl:when> is evaluated sequentially. The first node that matches is the one whose content is used If nothing matches, the content of <xsl:otherwise> is used <xsl:template match="*"> <xsl:choose> <xsl:when test="self::chapter"> I am a chapter. </xsl:when> <xsl:when test="self::appendix"> I am an appendix. </xsl:when> <xsl:otherwise> I don't know what I am. </xsl:otherwise> </xsl:choose> </xsl:template> XPath node set functions XSLT uses XPath expressions not only for matching, but for manipulating nodes too We can use all the node set function of XPath XPath node set functions There are also some functions that create node sets Numeric expressions A number in XSLT is defined to be a 64-bit floating point number, whether it has a decimal point or no Any expression type can be converted into Number: Numeric expressions XSLT provides a number of functions and operators to manipulate numeric values (actually, XPath functions) String expressions Any expression can be converted into a string using the string() function String expressions Creating strings: String expressions Operating on strings: Fine-tuning templates We have seen the basics of template rules and selection Now we will look on some ways of customizing the process outputting values node creation generating numbers and text sorting looping through node sets Outputting Node Values with <xsl:value-of> <xsl:value-of> is the tool for calculating and returning values May output text or numbers, for example: <xsl:value-of select=“count(//source)"/> May work on nodes, for example: <xsl:value-of select="."/> What is the value of a node? Let’s see how the value of a node is defined in XSLT: The values for each node type Root The root node inherits the value of the document element Element All the parsed character data in the element, together with the values of its descendants of type text and element only Attribute The value of the attribute with entities resolved, and leading and trailing whitespace removed The values for each node type Text All the text in the node Processing instruction Everything inside the processing instruction delimiters except the name Comment The text inside the comment delimiters Namespace The namespace's URI Outputting Node Values with <xsl:value-of> (continued) If <xsl:value-of> is applied to a set of nodes, only the first node's value is used May be confusing For processing a set of nodes, XSLT provides <xsl:for-each> element Looping with <xsl:for-each> <xsl:for-each> sets up a new context node set internally The following rule generates a table of contents: <xsl:template match="book"> <xsl:for-each select="chapter"> <xsl:value-of select="position()"/>. <xsl:value-of select="title"/>. </xsl:for-each> <xsl:apply-templates/> </xsl:template> This rule uses <xsl:for-each> to create a numbered list of chapter titles before processing each chapter with the <xsl:apply-templates> directive Creating nodes In order to create nodes, we can simply type them out in template rules Sometimes, the values of the nodes can be determined only in “runtime”, or through a complex process XSLT supply us additional tools for node creation Creating attributes <xsl:template match="entry"> <p>See the <a> <xsl:attribute name="href"> http://www.phone.com/<xsl:value-of select="@id"/> </xsl:attribute> catalog page </a> for more information. </p> </xsl:template> <xsl:attribute> created children attribute node for <a> We couldn’t create such href attribute by simply including it inside <a> element. Creating other nodes In addition to <xsl:attribute>, there is a directive for creating any type of nodes <xsl:element name=“expression”> <xsl:text> <xsl:comment> … <xsl:template match="thing"> <xsl:element name="{@type}"> <xsl:value-of select="."/> </xsl:element> </xsl:template> Creating other nodes <thing type="circle">radius: 3</thing> <thing type="square">side: 7</thing> Transformation from previous slide <circle>radius: 3</circle> <square>side: 7</square> Creating text nodes <xsl:text> Better control over white space Outputting forbidden characters like < and & disable-output-escaping attribute <xsl:template match="codelisting"> <h3>Code Example</h3> <pre> <xsl:text disable-output-escaping="yes"> cout &lt;&lt; "How to output strings in C++"; </xsl:text> </pre> </xsl:template> Outputting numbers <xsl:number value=“expression” format=“format string”> <xsl:value-of> offers a limited formatting: decimal numeric <xsl:number> offers more flexibility Sorting Imagine we have a telephone book document: <telephone-book> ... <entry id="44456"> <surname>Mentary</surname> <firstname>Rudy</firstname> <town>Simpleton</town> <street>123 Bushwack Ln</street> <phone>555-1234</phone> </entry> <entry id="44457"> <surname>Chains</surname> <firstname>Allison</firstname> <town>Simpleton</town> <street>999 Leafy Rd</street> <phone>555-4321</phone> </entry> ... </telephone-book> Sorting We want it to be displayed sorted by three keys: last name, first name and town By default, transformation will process the document in document order The entry with id=‘44456’ will be output before id=‘44457’ How can we sort? Sorting - <xsl:sort> Here is the solution: <xsl:template match="telephone-book"> <xsl:apply-templates> <xsl:sort select="town"/> <xsl:sort select="surname"/> <xsl:sort select="firstname"/> </xsl:apply-templates> </xsl:template> There are three sorting axes here. First, all the results are sorted by town. Next, the entries are sorted by surname. Finally, the entries are sorted by first name Example: Checkbook <?xml version="1.0"?> <!DOCTYPE checkbook SYSTEM "checkbook.dtd"> <checkbook> <deposit type="direct-deposit"> <payor>Bob's Bolts</payor> <amount>987.32</amount> <date>21-6-00</date> <description category="income">Paycheck</description> </deposit> <payment type="check" number="980"> <payee>Kimora's Sports Equipment</payee> <amount>132.77</amount> <date>23-6-00</date> <description category="entertainment">kendo equipment</description> </payment> <payment type="atm"> <amount>40.00</amount> <date>24-6-00</date> <description category="cash">pocket money</description> </payment> …… </checkbook> Example: Checkbook (cont’d) The output format is HTML, so it can be viewed in any web browser. The first template rule sets up the HTML page's structure and necessary tags: <xsl:template match="checkbook"> <html> <head/> <body> <!-- page content goes here --> </body> </html> </xsl:template> Example: Checkbook (cont’d) Let’s start with adding dates interval when payments were made. <xsl:template match="checkbook"> <html> <head/> <body> <!-- income information --> <h3> <xsl:text>Income from </xsl:text> <xsl:value-of select="child::*[1]/date"/> <xsl:text> until </xsl:text> <xsl:value-of select="child::*[last()]/date"/> <xsl:text>:</xsl:text> </h3> <xsl:apply-templates select="deposit"/> </body> </html> </xsl:template> <xsl:apply-templates select="deposit"/> - will output income transactions in the order they appear in the document. Example: Checkbook (cont’d) Now let's add a section to describe the deductions from the checking account, sorted by amount. <xsl:template match="checkbook"> <html> <head/> <body> <!-- income information --> <h3> ……………… </h3> <xsl:apply-templates select="deposit"/> <!-- payment information --> <h3> <xsl:text>Expenditures from </xsl:text> <xsl:value-of select="child::*[1]/date"/> <xsl:text> until </xsl:text> <xsl:value-of select="child::*[last()]/date"/> <xsl:text>, ranked from highest to lowest:</xsl:text> </h3> <xsl:apply-templates select="payment"> <xsl:sort data-type="number" order="descending" select="amount"/> </xsl:apply-templates> </body> </html> </xsl:template> Example: Checkbook (cont’d) Finally, let's display the account balance. We'll use <xsl:number> to calculate the sum of the transactions. Two sum() terms are necessary: one for the payment total and one for the income total. Then we'll subtract the total payment from the total income. To make it clear whether the user is in debt or not, we'll color-code the calculated result and print a warning if it's negative. Example: Checkbook (cont’d) <h3>Balance</h3> <p> <xsl:text>Your balance as of </xsl:text> <xsl:value-of select="child::*[last()]/date"/> <xsl:text> is </xsl:text> <tt><b> <xsl:choose> <xsl:when test="sum(payment/amount)>sum(deposit/amount)"> <font color="red"> <xsl:text>$</xsl:text> <xsl:value-of select="sum( deposit/amount ) - sum( payment/amount )"/> </font> </xsl:when> <xsl:otherwise> <font color="blue"> <xsl:text>$</xsl:text> <xsl:value-of select="sum( deposit/amount ) - sum( payment/amount )"/> </font> </xsl:otherwise> </xsl:choose> </b></tt> </p> Example: Checkbook (cont’d) <xsl:if test="sum( payment/amount ) > sum( deposit/amount )"> <p> <font color="red"> <xsl:text>DANGER! Deposit money quick!</xsl:text> </font> </p> </xsl:if> Example: Checkbook (cont’d) Let’s add some formatting to payment details output: Formulate nicely Add numbering <xsl:template match="payment"><p> <xsl:value-of select="position()"/> <xsl:text>. On </xsl:text> <xsl:value-of select="date"/> <xsl:text>, you paid </xsl:text> <tt><b> <xsl:text>$</xsl:text> <xsl:value-of select="amount"/></b></tt> <xsl:text> to </xsl:text> <i> <xsl:value-of select="payee"/> </i> <xsl:text> for </xsl:text> <xsl:value-of select="description"/> <xsl:text>.</xsl:text> </p></xsl:template> Example: Checkbook (cont’d) Previous template is not good when type="atm“. Let's make a special rule just for this case: <xsl:template match="payment[@type='atm']"> <p> <xsl:value-of select="position()"/> <xsl:text>. On </xsl:text> <xsl:value-of select="date"/> <xsl:text>, you withdrew </xsl:text> <tt><b> <xsl:text>$</xsl:text> <xsl:value-of select="amount"/> </b></tt> <xsl:text> from an ATM for </xsl:text> <xsl:value-of select="description"/> <xsl:text>.</xsl:text> </p> </xsl:template> Example: Checkbook (cont’d) Finally, let’s perform the same kind of formatting for deposits: <xsl:template match="deposit"> <p> <xsl:value-of select="position()"/> <xsl:text>. On </xsl:text> <xsl:value-of select="date"/> <xsl:text>, </xsl:text> <tt><b> <xsl:text>$</xsl:text> <xsl:value-of select="amount"/> </b></tt> <xsl:text> was deposited into your account by </xsl:text> <i> <xsl:value-of select="payor"/> </i> <xsl:text>.</xsl:text> </p> </xsl:template> Example: Checkbook (cont’d) Resulting HTML: <html><body> <h3>Income from 21-6-00 until 31-6-00:</h3> <p>1. On 21-6-00, <tt><b>$987.32</b></tt> was deposited into your account by <i>Bob's Bolts</i>.</p> <h3>Expenditures from 21-6-00 until 31-6-00, ranked from highest to lowest:</h3> <p>1. On 31-6-00, you paid <tt><b>$800.00</b></tt> to <i>Old Man Ferguson</i> for a 3-legged antique credenza that once belonged to Alfred Hitchcock.</p> <p>2. On 23-6-00, you paid <tt><b>$132.77</b></tt> to <i>Kimora's Sports Equipment</i> for kendo equipment.</p> <p>3. On 30-6-00, you paid <tt><b>$58.79</b></tt> to <i>Barnes and Noble</i> for O'Reilly Books.</p> <p>4. On 29-6-00, you paid <tt><b>$47.28</b></tt> to <i>Wild Oats Market</i> for groceries.</p> <p>5. On 24-6-00, you withdrew <tt><b>$40.00</b></tt> from an ATM for pocket money.</p> <p>6. On 26-6-00, you paid <tt><b>$36.86</b></tt> to <i>Lone Star Cafe</i> for lunch with Greg.</p> <h3>Balance</h3> <p>Your balance as of 31-6-00 is <tt><b><font color="red">$-128.38</font></b></tt> </p><p> <font color="red">DANGER! Deposit money quick!</font> </p> </body></html> Example: Checkbook (cont’d) Modes Sometimes we want to treat nodes differently depending on where they are used in the document. ( For example, we may want footnotes in tables to be alphabetized instead of numbered. ) To set up a mode, simply add a mode attribute set to a particular label to the affected <xsl:template> and template-calling elements. The mode label can be anything you want as long as it's unique among mode labels. Modes (example) <!– General template --> <xsl:template match="footnote"> <xsl:variable name="fnum" select="count(preceding::footnote[ancestor::chapter//.])+1"/> <a><xsl:attribute name="href"> <xsl:text>#FOOTNOTE-</xsl:text> <xsl:number value="$fnum" format="1"/> </xsl:attribute> <xsl:text>[</xsl:text> <xsl:number value="$fnum"/> <xsl:text>]</xsl:text></a> </xsl:template> <!– Specific template --> <xsl:template match="footnote" mode="tabular"> <xsl:variable name="fnum" select="count(preceding::footnote[ancestor::chapter//.])+1"/> <a><xsl:attribute name="href"> <xsl:text>#FOOTNOTE-</xsl:text> <xsl:number value="$fnum" format="1"/> </xsl:attribute> <xsl:text>[</xsl:text> <xsl:number value="$fnum" format="a"/> <xsl:text>]</xsl:text></a> </xsl:template> Modes (example cont’d) Usage: <xsl:template match="table-entry"> <xsl:apply-templates mode="tabular"/> </xsl:template> Named templates Instead of match attribute in template definition, you can specify name attribute We can call template explicitly by its name, using <xsl:calltemplate name=“..."/> Like function call in programming languages Can be defined and called with parameters Named templates - example <xsl:template name="navbar"> <a href="index.htm">Home</a> | <a href="help.htm">Help</a> | <a href="toc.htm">Contents</a> </xsl:template> <xsl:template match="mainblock"> <body> <xsl:call-template name="navbar"/> <xsl:apply-templates/> <xsl:call-template name="navbar"/> </body> </xsl:template> <xsl:template name="navbar"> <xsl:param name="title"></xsl:param> <xsl:value-of select="$title"/> Default value can <a href="index.htm">Home</a> | be put here <a href="help.htm">Help</a> | <a href="toc.htm">Contents</a> </xsl:template> <xsl:template match="mainblock"> <xsl:call-template name="navbar"/> <xsl:with-param name="title"> Navigate from this page </xsl:with-param> <xsl:apply-templates/> <xsl:call-template name="navbar"/> <xsl:with-param name="title"> Navigate from this page </xsl:with-param> </xsl:template> Variables Declared using <xsl:variable name=“name” select=“expression”> But, despite the name, can hold only constant initial value. Just like #define in C Declaration: <xsl:variable name="fnum“ select="count(preceding::footnote[ancestor::chapte r//.])+1"/> Usage: <xsl:number value=“$fnum”/> XSLT tools – development and debugging Altova XMLSPY Excellent support for creating, running and debugging XSLT, friendly and comfortable environment Many other features Altova Stylevision Visual stylesheet editor Many other features MarrowSoft <Xcelerator>: Editor Debugger Many other features XSLT tools for Web - client-side XSLT transformation Internet Explorer 5.0 was the first browser to support XSLT Internet Explorer 6.0 provides full support of XSLT (according to what Microsoft says), using Microsoft XML (MSXML) 3.0 parser Opera does not, and, as it seems now, will not support XSLT transformations in browser Mozilla supports, using TransforMiiX processor As expected, many problems start: Different HTML support and presentation Different whitespace handling Different syntax support… XSLT tools for Web - server-side XSLT transformation As we noticed, client-side transformations may be problematic There are browsers that do not support XSLT Different browsers may display differently the result The transformation can be performed on the server’s side Altova offers free XSLT command line parser, which uses exactly the same engine that XMLSPY uses Microsoft offers MSXML parser for download Useful XSLT resources http://www.w3.org/TR/xslt Official XSLT specification http://www.topxml.com/xsl/tutorials/intro/default.asp Excellent XSLT tutorial The end! Questions?