XSLT


Think of XSLT programming style as an event driven program, and event listeners (xsl:template) as the behavior of the program. The input XML file will be read by the program as a stream, and once a new declared event happened (template) it will be executed.

If in applying templates it doesn't find a template starting at root, it will traverse all tags and if finds a mtach for one will execute the match, otherwise will display its text. - match statements must be starting from the current node or having a // to be findable.




Hello World XML:

<?xml version="1.0" encoding="ISO-8859-1"?>
<greeting>Hello World!</greeting>


you can inlude reference to the xsl file in the xml file and when openning the xml file in a browser it will display the transformed xml.. Just add the following line after the xml declaration in the xml file
<?xml-stylesheet type="text/xsl" href="1.xsl"?>


Hello World xslt transformer
<?xml version="1.0" encoding="ISO-8859-1"?>
<html xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xsl:version="2.0">
<head><title>Hello World Title</title></head>
<body><p><xsl:value-of select="/greeting"/></p></body>
</html>

File names shoul not start with a number!

A bash file to execute SAXON to transform the xml file

./run_transform.sh
#!/bin/bash
CLASSPATH=./saxon9he.jar
export CLASSPATH
java net.sf.saxon.Transform -o temp.xml $1 reorder_xform.xsl

This will need an input argument (the xml file) usin the reorder_xform.xslin the current directory, transforms it to the temp.xml in the current directory.

If namespace is not specified for an xml element or an attribute, they are in the default namespace, unless they have explicitly specified the namespace.

Namespace prefix doesn't matter as long as the namespace URI is the same.

<xsl:for-each>

To cycle through a list of elements of same type:
<xsl:for-each select="/TVGuide/Channel">
The title is: <xsl:value-of select="name"/>
<xsl:for-each select="program">
Program: <xsl:value-of select="series"/>
Cast List:
 <xsl:for-each select="cast">
<xsl:value-of select="Actor"/>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>

Relative paths are always evaluated relative to the context node (current node).

<xsl:apply-templates>

Modularize the XSLT code into templates and call the template right in place.
Write templates as the main children of the document and call them with <xsl:apply-templates selsct="program"/>

If <xsl:apply-templates> does not have a select attribute, the XSLT processor will collect all the children of the current node (nodes that template matches) and applies templates to them. If they have a template associated with them it will be called otherwise their text content will be returned.

If you apply a template to an element but there is no template for that element, the text within the element will be returned. E.g. if we have used <xsl:apply-templates select="name"/> but we have not defined the template for "name", then the text value of the element will be returned -text at all levels concatenated).
For example if we have :     some text <character>Mary</character> more text    and apply the following to it:
<xsl:template match="character"> <xsl:apply-templates /> </xsl:template>
the txtual content of all the children at all levels will be concatenated together and returned.

Selecting Nodes

/ Matches the document node
* Matches any element
text() Matches text nodes
<xsl:template match="text()">  #text() matches text nodes
<xsl:value-of select="."/>
</xsl:template>
name of an element matches that element

castMember/character: direct child
description//character:  character nested to any level of description

Pattern Priority

  • Patterns that match a class of nodes e.g. * are -0.5
  • Patterns that match according to the name of the tag are 0
  • Patterns that match according to their decendancy e.g. books/book1 or books//book1 are 0.5
  • You can explicitly assign priority of a template:   <xsl:template match="a/b" priority="2">  </xsl:template>

<xsl:next-element>

tells the XSLT processor to find the next most applicable template rule for the context node being processed and apply it, letting you apply multiple template rules to a node while still using a push approach(stand-alone templates). Link

"Go find the next most appropriate template rule after this one, execute all of its instructions, and then resume in this template rule."

you can add xsl:with-param children to the xsl:next-match element to pass parameters, just like you can with named templates.


<xsl:text> </xsl:text>

for explicit text outputs - recommended for preserving whitespaces.

<xsl:variable>

<xsl:variable> name="foo" value="123" />
<xsl:variable name="bar" value="456" />
<xsl:variable name="baz" value="$foo + $bar" />
<xsl:variable name="dummy" value="42 div 0" />
<xsl:template match="/">
<xsl:value-of select="$baz"/>
</xsl:template>

make the result of a template as a variable and call it in another template:
<xsl:variable name="var_template1">
<xsl:apply-templates select="template1" />
</xsl:variable>
<xsl:apply-templates select="template2">
<xsl:with-param name="var_template1" select=$var_template1 />
</xsl:apply-templates>

<xsl:import> <xsl:include>

Used to import xsl codes from other files, with template override capabilities.


<xsl:choose>
<xsl:when test="attribute::ca = 'l'">
<xsl:text>left</xsl:text>
</xsl:when>       
<xsl:when test="attribute::ca = 'c'">
<xsl:text>center</xsl:text>
</xsl:when>
</xsl:choose>















Comments