http://exslt.org/math
math
Většina XSLT procesorů podporuje i výpočtové matematické funkce – goniometrické funkce, logaritmy a exponenciální funkce. Můžeme je využít ve stylech, které provádějí složitější výpočty.
Představme si, že máme nějakou statistiku v podobě dokumentu XML.
Příklad 13.7. Statistická data jako dokument XML –
prohlizece.xml
<?xml version="1.0" encoding="utf-8"?> <prohlizece> <klient podil="69.5">IE6</klient> <klient podil="6.5">IE5</klient> <klient podil="2.4">Opera 7</klient> <klient podil="16.6">Mozilla</klient> <klient podil="0.2">NN3</klient> <klient podil="0.2">NN4</klient> <klient podil="1.4">NN7</klient> </prohlizece>
Nyní ji chceme prezentovat v přehledné podobě jako koláčový graf. I pro tento úkol zdánlivě nesouvisející s XML a XSLT, nemusíme používat jiné technologie. Vektorové obrázky lze reprezentovat formátu SVG, který je založen na XML. Není tedy příliš složité převést data v XML do SVG právě pomocí transformace XSLT. Protože při vytváření koláčového grafu potřebujeme spočítat souřadnice bodů ležící na kruhu, využijeme s výhodou matematické funkce EXSLT.
Příklad 13.8. Generování XHTML+SVG –
kolacovy-graf.xsl
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:svg="http://www.w3.org/2000/svg" xmlns:math="http://exslt.org/math" xmlns:b="urn:x-kosek:barvy" extension-element-prefixes="math" exclude-result-prefixes="b" version="1.0"> <!-- <xsl:output doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/> Protože je IE prasátko a neumí korektně zpracovat XHTML, musíme mu SVG vložit do něčeho, co je spíše HTML. Fuj! :-( V Opeře 8 to funguje dobře, stačí nechat method="xml" --> <xsl:output method="html"/> <!-- Konstanta π --> <xsl:variable name="pi" select="3.1415926535"/> <!-- Kódy barev, které se postupně použijí pro jednotlivé výseče grafu --> <b:barvy> <barva>#FF7D00</barva> <barva>#B35800</barva> <barva>#FFDFBF</barva> <barva>#FFBE80</barva> <barva>#006EB0</barva> <barva>#004D7B</barva> <barva>#BFE7FF</barva> <barva>#80CFFF</barva> <barva>#320199</barva> <barva>#23016B</barva> <barva>#D4C0FF</barva> <barva>#A980FF</barva> <barva>#FFCB00</barva> <barva>#B38E00</barva> <barva>#FFF2BF</barva> <barva>#FFE580</barva> </b:barvy> <!-- Celkový počet definovaných barev --> <xsl:variable name="pocetBarev" select="count(document('')//b:barvy/barva)"/> <!-- Hlavní šablona --> <xsl:template match="prohlizece"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Statistika prohlížečů</title> <!-- Kód vyžadovaný Adobe SVG pluginem pro IE --> <object id="AdobeSVG" classid="clsid:78156a80-c6a1-4bbf-8e6a-3cd390eeb4e2"></object> <xsl:processing-instruction name="import">namespace="svg" implementation="#AdobeSVG"</xsl:processing-instruction> </head> <body> <h1>Statistika prohlížečů</h1> <table border="0"> <tr> <td> <!-- Začátek SVG obrázku --> <svg:svg viewBox="0 0 2.1 2.1" width="10cm" height="10cm"> <svg:g transform="translate(1.05,1.05) scale(1,-1)"> <xsl:variable name="celkem" select="sum(klient/@podil)"/> <xsl:variable name="pomerUhlu" select="2 * $pi div $celkem"/> <!-- Pro každý prohlížeč se vygeneruje jedna výseč v grafu --> <xsl:for-each select="klient"> <xsl:variable name="x1" select="format-number(math:cos(sum(preceding-sibling::klient/@podil) * $pomerUhlu), '0.####')"/> <xsl:variable name="y1" select="format-number(math:sin(sum(preceding-sibling::klient/@podil) * $pomerUhlu), '0.####')"/> <xsl:variable name="x2" select="format-number(math:cos((sum(preceding-sibling::klient/@podil) + @podil) * $pomerUhlu), '0.#####')"/> <xsl:variable name="y2" select="format-number(math:sin((sum(preceding-sibling::klient/@podil) + @podil) * $pomerUhlu), '0.#####')"/> <xsl:variable name="uhel" select="@podil * $pomerUhlu"/> <xsl:variable name="large-arc"> <xsl:choose> <xsl:when test="$uhel >= $pi">1</xsl:when> <xsl:otherwise>0</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="pos" select="position()"/> <xsl:variable name="fill" select="document('')//b:barvy/barva[($pos mod $pocetBarev) + 1]"/> <svg:path d="M 0,0 L {$x1},{$y1} M {$x1},{$y1} A1,1 0 {$large-arc} 1 {$x2},{$y2} L 0,0" style="stroke:black; stroke-width: 0.005; fill:{$fill}"/> </xsl:for-each> </svg:g> </svg:svg> </td> <td> <!-- Vygenerováné legendy ke grafu --> <table cellpadding="4" cellspacing="4"> <xsl:for-each select="klient"> <xsl:variable name="pos" select="position()"/> <xsl:variable name="fill" select="document('')//b:barvy/barva[($pos mod $pocetBarev) + 1]"/> <tr> <td bgcolor="{$fill}" width="20px" height="20px"> </td> <td><xsl:value-of select="."/> (<xsl:value-of select="@podil"/> %)</td> </tr> </xsl:for-each> </table> </td> </tr> </table> </body> </html> </xsl:template> </xsl:stylesheet>