I. Introduction
XSLT stands for Extensible Stylesheet Language Transformation. It is a programming language used to transform XML documents in various formats like HTML and ... XML :-)
XSLT has many processing functions that make it a complete programming language. You can create "functions", loops, calculate a maximum, doing research in an XML document, counting the number of results, and so on. But XSLT is primarily oriented processing an XML file. We will implement models (templates) on XML tags, and then apply their treatment.
This article is an introduction to XSLT, for functions more "advanced", see my article in XSLT Programmer.
II. Example
II.A. Documents and codes
Currently XML source (liste.xml):
<? xml version = "1.0" encoding = "ISO-8859-1"?>
<liste_nombres>
<number valeur="10"> ten </ number>
<number valeur="0"> zero </ number>
<number valeur="33"> thirty-three </ number>
<number valeur="6"> the first perfect number </ number>
</ liste_nombres>
XSLT stylesheet (xslt.xsl):
<? xml version = "1.0" encoding = "ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl: output
method = "html"
encoding = "ISO-8859-1"
doctype-public ="-// W3C / / DTD HTML 4.01 / / EN "
doctype-system = "http://www.w3.org/TR/html4/strict.dtd"
indent = "yes" />
<xsl:template match="liste_nombres">
<html> <body>
<p> list of numbers: </ p>
<ul>
<xsl:apply-templates select="nombre" />
</ ul>
</ body> </ html>
</ xsl: template>
<xsl:template match="nombre">
<li>
<xsl:value-of select="@valeur" />
<xsl:text>: </ xsl: text>
<xsl: value-of select = "." />
</ li>
</ xsl: template>
</ xsl: stylesheet>
In PHP, you can use this script:
<?
/ / Create the XSLT processor
$ xh = xslt_create ();
xslt_set_base ($ xh, 'file: / /'. getcwd ().'/');
/ / Treaty document, then displays the result
$ result = xslt_process ($ xh, 'liste.xml', 'xslt.xsl');
if ($ result)
echo ( "Error XSLT ...");
Else
echo ($ result);
/ / Destroys processor XSLT
xslt_free ($ xh);
?>
II.B. Expected result
You should get the following result:
List of numbers:
* 10: Ten
* 0: zero
* 33: thirty-three
* 6: the first perfect number
In HTML code, it provides:
<! DOCTYPE html PUBLIC "-//W3C//DTDHTML 4.01 / / EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<body>
<p> list of numbers: </ p>
<ul>
<li> 10: Ten </ li>
<li> 0: zero </ li>
<li> 33: thirty-three </ li>
<li> 6: the first perfect number </ li>
</ ul>
</ body>
</ html>
II.C. Explanation
Consider the XSLT code in detail. Already we can see a sheet XSLT is written ... XML ;-)
| Code | Explanation |
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> | This tag contains the version used XSLT (1.0 here), and a link to the namespace (namespace, abstract ns, xslns). To use version 1.0, you must ABSOLUTELY use this link. In decoded, cut and paste this line without question you pose ;-) were then tag: |
<xsl:output method="html" encoding="ISO-8859-1" doctype-public="-//W3C//DTD HTML 4.01//EN" doctype-system="http://www.w3.org/TR/html4/strict.dtd" indent="yes" />
| This tag indicates the output format. Here I wish to HTML encoded in ISO-8859-1. "doctype-public" is the name of the standard respected (I chose HTML 4.01). "doctype-system" is a link to the DTD this standard. See W3.org to choose your standard and specify the correct link. Finally, "indent = yes" indicates that the file will be generated automatically indented. Not just in fun to indent the HTML code within the XSLT stylesheet: XSLT engine takes care ;-) By the way, disable indentation reduces the size of files generated ... It's up to you. We spent part barbante well, entering the heart of the matter! |
| <xsl:template match="liste_nombres"> | This tag is a function XSLT which will be called whenever the tag is encountered liste_nombres (match = "liste_nombres"). They call it a model (template). As is our beacon root, it will have to write the HTML header at this location there. |
| <xsl:apply-templates select="nombre" /> | Another function XSLT which "calls" the other models for girls named tag number (select = "number"). More generally, it could apply to other models all son with select = "*" (* = any tag girl). |
| <xsl:value-of select="@valeur" /> | It is here to read the content of the attribute appointed value. In the same way we read the contents (outside tags girls) by the query select = "." (. Is the current path = current node of the tree XML). |
II.D. Trions result
This example is not very useful. So the pay more attractive by sorting the result. Just change two lines of code! Simply replace:
<xsl:apply-templates select="nombre" />
by
<xsl:for-each select="nombre">
<xsl:sort select="@valeur" />
<xsl: apply-templates select = "." />
</ xsl: for-each>
Result:
List of numbers sorted:
* 0: zero
* 10: Ten
* 33: thirty-three
* 6: the first perfect number
It works ... But this is not what we want. The numbers are sorted by characters characters (0, 1, 3, 6: they are in order). It must then be corrected by specifying the type of data: there are numbers!
<xsl:sort select="@valeur" data-type="number" />
And this is the work ;-) Too easy ... Stronger, we can reverse the list by adding attribute order = "descending" (in descending order) the tag fate.
So you begin to receive the benefit of XML and XSLT?
III. Duplicating tags and texts
III.A. Code naive
If you do not want to write a model for all tags, it will sooner or later write two generic models: one for attributes, another for the tags. This gives us:
<xsl:template match="@*">
<xsl:copy />
</ xsl: template>
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates select="* | text() |*"/>
</ xsl: copy>
</ xsl: template>
III.B. Problem and solution
If you use the code given above, you'll have problems namespace (namespace) with tags that look like this:
<div xmlns:xsl="http://www.w3.org/1999/XSL/Transform" class="baniere">
This is because the tag xsl: copy copy also namespace XSLT engine ... Solution:
<xsl:template match="@*">
<xsl:copy />
</ xsl: template>
<xsl:template match="*">
<xsl:element name="{name()}">
<xsl:apply-templates select="* | text() |*"/>
</ xsl: element>
</ xsl: template> 1
IV. Problems
IV.A. Avoiding a little cumbersome XSLT with accolades
When I wrote my first pages XSLT, I wrote my very proper tags:
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="lien" />
</ xsl: attribute>
<xsl:value-of select="texte" />
</ xsl: element>
I do not know what you say, but personal, I find it very heavy just to post a link! The solution: the accolades. These last in the value of an attribute replace a xsl: value-of. Example equivalent to the example above:
<a href="{lien}">
<xsl:value-of select="texte" />
</ a>
This is shorter, nan? You can do many things in accolades, but not all, of course (no xsl: if, for example). Examples use the concatenation: href = "(concat ($ repertoire ,'/',$ nomfich))". I have not pushed too far tests, but I think all functions XPATH are used ;-)
IV.B. Remove spaces due to the indentation XML
When I write an XML document, I like my indent code to get a good readability. But the problem is that in some cases, would like to remove these spaces! Example any beast:
<p>
<a href="http://www.developpez.com"> Developpez.com </ a>:
The developers' paradise!
</ p>
Without any change, the HTML code will be generated (indentation XSLT enabled):
<html>
<body>
<p>
<a href="http://www.developpez.com"> Developpez.com </ a>:
The developers' paradise!
</ p>
</ body>
</ html>
It's not very pretty: - / There are then two commands XSLT to address the problems:
<xsl:strip-space elements="*" />
<xsl:preserve-space elements="pre | code" />
"strip-space" will remove unnecessary spaces of all tags. But HTML tags and pre code must retain their indentation, they wrote in the order XSLT "preserve-space" (tags are separated by the'|'). By default, all spaces are preserved.
IV.C. Remove spaces due to the indentation XSLT
In the same manner as XML, I like my indent XSLT code. Example:
<! - Version indigestible ->
<xsl:template match="lien">
<a href="{href}"> <xsl:value-of select="nom" /> </ a>: <xsl:value-of select="description" />
</ xsl: template>
<! - Version indented ->
<xsl:template match="lien">
<a href="{href}">
<xsl:value-of select="nom" />
</ has>
:
<xsl:value-of select="description" />
</ xsl: template>
The problem is that the exit gives something like:
<a href="http://www.developpez.com"> Developpez.com </ a>
:
The developers' paradise!
The solution: use tags XSLT "xsl: text". This tag allows you to write properly text within a tag. The ideal would be to use that tag, but in practice we use it only when it is most needed (no wild bee). This gives the final XSLT code:
<xsl:template match="lien">
<a href="{href}">
<xsl:value-of select="nom" />
</ a>
<xsl:text>: </ xsl: text>
<xsl:value-of select="description" />
</ xsl: template>
V. Conclusion
We made a quick tour of XSLT, and some problems encountered. You could see how it works, and you could see the power of XSLT. But quickly read my article in XSLT Programmer to see what XSLT really in the belly ;-)