Translate

Translate to EnglishÜbersetzen Sie zum Deutsch/GermanΜεταφράστε στα ελληνικά/GreekПереведите к русскому/RussianOversetter til Norsk/NorwegianÖversätta till Svensk/Swedishहिन्दी अनुवाद करने के लिए/Hindi
Tradueix al català/CatalanTulkot uz latviešu/LatvianPreložiť do slovenčiny/SlovakVertaal aan het Nederlands/Dutchترجمة الى العربية/ArabicTraduzca al Español/SpanishTraduisez au Français/French
Traduca ad Italiano/ItalianTraduza ao Português/Portuguese日本語に翻訳しなさい /Japanese한국어에게 번역하십시오/Korean中文翻译/Chinese Simplified中文翻译/Chinese TraditionalПереклад на українську/Ukrainian
Image of Beginning Google Maps API 3
Image of Advanced Programming in the UNIX Environment, Second Edition (Addison-Wesley Professional Computing Series)
Image of Android Wireless Application Development
Image of Modern Operating Systems (3rd Edition)

XSLT 1.0 Multiple Namespace Issues

This post discusses namespaces in XML documents and XSLT 1.0 stylesheets. In particular, it demonstrates a number of techniques to control namespace prefixes and declarations in outputted documents.

XSLT Variable Arrays

I recently answered a question on a popular programmers forum about how to store and access an array of user-defined variables in a stylesheet and then loop though those variables.  I realized that many developers are not familar with the available techniques for doing this and decided to add an entry in my blog about this topic.

User-defined variable arrays within stylesheets are not part of the XSLT specification.  The usual way to handle this problem in XSLT 1.0 stylesheets is to define a user-defined top-level element which belongs to a non-null namespace which is different from the XSLT namspace.  These user-defined top-level elements are typically used to store error messages, lookup data, etc.  You can then access these user-defined elements from within your stylesheet by treating the stylesheet as an additional source document and loading it using the document() function with an empty string as the first argument.  An empty string is interpreted to mean the current stylesheet.

The following stylesheet demonstrates this method. <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:foo="http://foo.com" exclude-result-prefixes="foo"> <xsl:output method="text" encoding="utf-8"/> <foo:vars> <foo:var name="z1">A</foo:var> <foo:var name="z2">B</foo:var> <foo:var name="z3">C</foo:var> <foo:var name="z4">D</foo:var> </foo:vars> <xsl:template match="/"> <xsl:for-each select="document(”)/xsl:stylesheet/foo:vars/foo:var" > <xsl:value-of select="." /> <xsl:if test="position() != last()"> <xsl:text>,</xsl:text> </xsl:if> </xsl:for-each> <xsl:text> </xsl:text> </xsl:template> </xsl:stylesheet>

If you are using XSLT 2.0, this method is no longer needed as simpler and more elegant methods are available to us.  For example, you can store and directly access the variables using the <xsl:variable> element as shown in the following stylesheet. <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" > <xsl:output method="text" encoding="utf-8"/> <xsl:variable name="z1" select="’A'" /> <xsl:variable name="z2" select="’B'" /> <xsl:variable name="z3" select="’C'" /> <xsl:variable name="z4" select="’D'" /> <xsl:variable name="vars" select="$z1, $z2, $z3, $z4" /> <xsl:template match="/"> <xsl:for-each select="$vars" > <xsl:value-of select="." /> <xsl:if test="position() != last()"> <xsl:text>,</xsl:text> </xsl:if> </xsl:for-each> <xsl:text> </xsl:text> </xsl:template> </xsl:stylesheet>

Another way to store and access this data in a XSLT 2.0 stylesheet is to use a global variable definition as shown below. <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" > <xsl:output method="text" encoding="utf-8"/> <xsl:variable name="vars"> <var name="z1">A</var> <var name="z2">B</var> <var name="z3">C</var> <var name="z4">D</var> </xsl:variable> <xsl:template match="/"> <xsl:for-each select="$vars/var" > <xsl:value-of select="." /> <xsl:if test="position() != last()"> <xsl:text>,</xsl:text> </xsl:if> </xsl:for-each> <xsl:text> </xsl:text> </xsl:template> </xsl:stylesheet>

All three stylesheets output the same data.

You may be wondering about this image.  It is from the screen of my laptop.  I used xsltproc on Microsoft Vista SUA for the XSLT 1.0 transformation and Saxon 9 in Microsoft Powershell v2.0 CTP2 for the two XSLT 2.0 transformations.

Note that the

XSLT Copy with Exception

A recent problem that was posed to me concerned how to copy the entire contents of an XML document with certain exceptions.  Turns out that the simplest way to handle this requirement in XSLT1.0 was to include the standard XSL identity template in my stylesheet and add another template to handle the exception.

A simple example will make things clearer.  Suppose we have the following XML document (which I shamelessly copied from W3Schools.com and modified to simplify) and we want to copy this document in its entirety except for details of CDs by a specific artist. <?xml version="1.0"?> <CATALOG> <CD> <TITLE>Empire Burlesque</TITLE> <ARTIST>Bob Dylan</ARTIST> <COUNTRY>USA</COUNTRY> <COMPANY>Columbia</COMPANY> <YEAR>1985</YEAR> </CD> <CD> <TITLE>Hide your heart</TITLE> <ARTIST>Bonnie Tyler</ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>CBS Records</COMPANY> <YEAR>1988</YEAR> </CD> <CD> <TITLE>Greatest Hits</TITLE> <ARTIST>Dolly Parton</ARTIST> <COUNTRY>USA</COUNTRY> <COMPANY>RCA</COMPANY> <YEAR>1982</YEAR> </CD> <CD> <TITLE>One night only</TITLE> <ARTIST>Bee Gees</ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>Polydor</COMPANY> <YEAR>1998</YEAR> </CD> <CD> <TITLE>Sylvias Mother</TITLE> <ARTIST>Dr.Hook</ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>CBS</COMPANY> <YEAR>1973</YEAR> </CD> <CD> <TITLE>Maggie May</TITLE> <ARTIST>Rod Stewart</ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>Pickwick</COMPANY> <YEAR>1990</YEAR> </CD> </CATALOG>

Below is the stylesheet.  It accepts one parameter, i.e. the name, or part of the name, of an artist.  It copies all nodes and attributes to the output document except those nodes and attributes related to the artist whose name matches or is is a superset of the inputted string. <?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:param name="artist"></xsl:param> <xsl:output method="xml"/> <xsl:template match="node() | @*"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <xsl:template match="/CATALOG/CD"> <xsl:if test="not(contains(./ARTIST,$artist))"> <xsl:copy-of select="." /> </xsl:if> </xsl:template> </xsl:stylesheet>

The first template is the standard identity template from the XSL 1.0 Transformations Recommendation.  It matches all attributes and all nodes being children of other nodes, and copies them to the output document.   The second template cancels the automatic copying of the <CD> nodes and children, checks to see that the name, or part of the name, of the artist does not match the search string, and only does a deep copy of the nodes and attributes to the output document if there is no match.

Assuming you are on a Linux system, you can use the command line utility xsltproc (which is part of the XSLT C library for GNOME) to transform the input document into the following output document when &quotStewart&quot is passed as a parameter to the stylesheet.  BTW, note the use of Java style string quotes for the parameter string. $ xsltproc -param artist "’Stewart’" file.xsl file.xml

Here is the output document. It is a copy of the input document except the "record" for the Rod

XSLT Dynamic Path Evaluation

This post discusses the problem of dynamic XPath expression evaluation in XSLT 1.0 and XSLT 2.0 and how to handle it using an EXSLT extension function.

XSLT DateTime Formatting

Support for date and time formating in the XSLT 1.0 specification is non-existent. This did not mean that a person cannot format date and time strings using XSLT 1.0; it just makes it much harder to do so and adds many extra lines of code to stylesheets. However it is something that everybody who develops stylesheets ends up having to do. In this post I show you several ways to format dates in XSLT 1.0 and discuss some of the new dateTime formating and manipulation functions in XSLT 2.0 and XPath 2.0.