Ukázka XSLT stylesheetu

Jazyk XSL (XML Stylesheet Language) převádí dokumenty ve formátu XML (Extensible Markup Language) na XML anebo libovolný jiný text. Při hrubém pohledu jde o seznam šablon, a každá z nich změní kousek vstupního dokumentu na kousek výstupu. Zvědavější zkoumání ale odhalí, že je to programovací jazyk se vším všudy: proměnné, výpočty, podmínky, volání funkcí.

Na druhou stranu, některé obvyklé nástroje nám budou chybět. Například, klasický for nebo while cyklus nemáme, a přepsat ho vyžaduje chytré použití rekurze (šablona, která bude při splnění podmínky volat sama sebe).

Ukázky

XML dokument převedený na HTML anebo na SVG.

Původní dokument:

<?xml version="1.0" ?>
<?xml-stylesheet href="html.xslt" type="text/xsl" ?>
<dokument>
<diagram>
	<skupina>
		<velikost>50</velikost>
	</skupina>
	<skupina>
		<velikost>50</velikost>
	</skupina>
</diagram>
<diagram>
	<skupina>
		<velikost>25</velikost>
	</skupina>
	<skupina>
		<velikost>75</velikost>
	</skupina>
</diagram>
</dokument>

HTML ukázka používá <xsl:for-each> na výpis všech diagramů v dokumentu, a funkci position() na jejich číslování. O pár řádku níže pak diagramy vypíše znovu, tentokrát pomocí <xsl:apply-templates>. Jako perlička mají diagramy nastavené id a aktivní blok se podbarví žlutě pomocí CSS selektoru :target.

<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/dokument">
<html>
	<head>
		<meta charset="utf-8"></meta>
		<title>HTML výstup</title>
		<style>
			h2:target + ul {
				background-color: #ffc;
			}
		</style>
	</head>
	<body>
	<h1>Zobrazené skupiny:</h1>
	<ul>
	<xsl:variable name="i" select="70"/>
	<xsl:for-each select="diagram">
		<li><a href="#diagram_{position()}">Diagram <xsl:value-of select="position()"/></a></li>
	</xsl:for-each>
	</ul>

	<xsl:apply-templates select="diagram">
	</xsl:apply-templates>
 </body>
</html>
</xsl:template>

<xsl:template match="diagram">
<h2 id="diagram_{position()}">Diagram <xsl:number value="position()" format="I"/></h2>
<ul style="border: 1px solid black;">
	<xsl:for-each select="skupina">
	<xsl:sort select="velikost" order="descending"/>
	<li><xsl:value-of select="velikost"/> prvků </li>
	</xsl:for-each>
</ul>
</xsl:template>
</xsl:stylesheet>

SVG ukázka používá dvakrát za sebou <xsl:apply-templates> s různými parametry, aby nejdřív namalovala vnitřek kruhů a pak je obtáhla černě. Pozice kruhů na stránce je spočítaná pomocí XPath selektorů.

<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/2000/svg">
<xsl:output method="xml" indent="yes" standalone="no" doctype-public="-//W3C//DTD SVG 1.1//EN" doctype-system="http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" media-type="image/svg" />

<xsl:template match="dokument">
<svg xmlns="http://www.w3.org/2000/svg">
<style>
	circle { fill:none; stroke: black; }
	circle.plny { fill: rgba(255, 0, 0, 0.5); stroke: none; }
	g:target circle.plny { fill: rgba(255, 200, 0, 0.5); }
	text { dominant-baseline: central; text-anchor: middle; }
</style>
<xsl:apply-templates select="diagram">
</xsl:apply-templates>
</svg>
</xsl:template>

<xsl:template match="diagram">
<g id="diagram_{position()}">
<xsl:apply-templates select="skupina">
	<xsl:with-param name="css-class" select="'plny'"/>
	<xsl:with-param name="pozice" select="100*(position()-1)"/>
</xsl:apply-templates>
<xsl:apply-templates select="skupina">
	<xsl:with-param name="css-class" select="'obtazeny'"/>
	<xsl:with-param name="pozice" select="100*(position()-1)"/>
</xsl:apply-templates>
</g>
</xsl:template>

<xsl:template match="skupina">
	<xsl:param name="pozice"/>
	<xsl:param name="css-class"/>
	<xsl:variable name="x">
		<xsl:choose>
			<xsl:when test="count(preceding-sibling::skupina) > 0"><xsl:value-of select="(preceding-sibling::node()/velikost) - 8"/></xsl:when>
			<xsl:otherwise>0.1</xsl:otherwise>
		</xsl:choose>
	</xsl:variable>
	<circle class="{$css-class}" cx="{$x + velikost div 2}" cy="{$pozice+50}" r="{velikost div 2}" />
	<text x="{$x + velikost div 2}" y="{$pozice+50}"><xsl:value-of select="velikost"/></text>
</xsl:template>
</xsl:stylesheet>