Ve většině javových procesorů lze volat externí funkce. Je potřeba definovat jmenný prostor, který namapuje určitou třídu na prefix jmenného prostoru. Volání metod a vytvoření nového objektu je přizpůsobeno syntaxi XPath výrazů.
Příklad 12.3. Volání javového kódu – datum.xsl
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:date="java.util.Date" extension-element-prefixes="date"> <xsl:output method="text"/> <xsl:template match="/"> <xsl:value-of select="date:to-string(date:new())"/> </xsl:template> </xsl:stylesheet>
Obdobným způsobem můžeme do dokumentu přidat i volání vlastního javového kódu.
Podobnou možnost nabízí i další procesory – např. MSXML. Můžeme si definovat vlastní funkce v JScriptu nebo VBScriptu a používat je jako nativní XPath funkce. Uvnitř funkcí můžeme používat všechny konstrukce jazyka, vytvářet instance COM objektů, volat jejich metody apod. Následující ukázka ukazuje, jak v MSXML pomocí JScriptu zjistit aktuální datum a pracovat s regulárními výrazy.
Příklad 12.4. Definice vlastních funkcí v MSXML – msxsl.xsl
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:moje="http://moje.cz/mujns"> <msxsl:script language="JScript" implements-prefix="moje"> function datum() { var d = new Date(); return d.toLocaleString(); } function match(value, pattern) { re = new RegExp(pattern); if (typeof(value) == 'string') s = value; else s = value.nextNode.text; return re.test(s); } </msxsl:script> <xsl:output method="text" encoding="utf-8"/> <xsl:template match="/"> <xsl:text>Dnes je: </xsl:text> <xsl:value-of select="moje:datum()"/> <xsl:text>
</xsl:text> <xsl:text>Počet uzlů, které obsahují jen číslo: </xsl:text> <xsl:value-of select="count(//*[moje:match(.,'^[0-9]+$')])"/> </xsl:template> </xsl:stylesheet>
Pro definici vlastních funkcí musíme použít instrukci
<msxsl:script>
, musíme mít samozřejmě
definován správný jmenný prostor. Pro vlastní funkce si pak
deklarujeme další jmenný prostor a jeho prefix uvádíme v atributu
implements-prefix
. Funkci můžeme předat nejen
skalární hodnotu, ale i seznam uzlů. Ten je předán ve stejné
kolekci, jako když použijeme metodu
selectNodes()
. Podrobnou dokumentaci
k API MSXML najdete v [15].
Možnost vytváření vlastních funkcí je potřeba v MSXML použít častěji, než bychom si sami přáli. Chceme-li například implementovat alespoň s určitými omezeními výstup do několika souborů, musíme si napsat vlastní funkci, která fragment výstupního XML dokumentu uloží do samostatného souboru.
Příklad 12.5. Výstup do více souborů v MSXML – katalog-soubory3.xsl
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:file="urn:x-kosek:xslt:file" extension-element-prefixes="msxsl file" exclude-result-prefixes="msxsl file"> <xsl:import href="katalog-obrazky.xsl"/> <msxsl:script language="JScript" implements-prefix="file"> <![CDATA[ // definice funkce pro zápis do souboru function write(nodes, outputFile) { var fso = new ActiveXObject("Scripting.FileSystemObject"); var file = fso.CreateTextFile(outputFile, true); try { for (var i = 0; i < nodes.length; i++) { file.Write(nodes.item(i).xml); } } finally { file.Close(); delete fso; delete file; } return ""; } ]]> </msxsl:script> <xsl:template match="/"> <!-- Uložení obsahu úvodní stránky do proměnné --> <xsl:variable name="content"> <xsl:apply-imports/> </xsl:variable> <!-- Otestujeme, zda bude zápis do souborů fungovat --> <xsl:if test="not(function-available('file:write'))"> <xsl:message terminate="yes"> Tento styl musíte zpracovat XSLT procesorem z MSXML. </xsl:message> </xsl:if> <xsl:value-of select="file:write($content, 'katalog.html')"/> </xsl:template> <xsl:template match="nazev"> <TH> <A href="{generate-id(..)}.html"> <xsl:apply-templates/> </A> </TH> </xsl:template> <xsl:template match="polozka" mode="detailni"> <!-- Obsah celého generovaného souboru si uložíme do jedné proměnné, protože ho budeme používat opakovaně --> <xsl:variable name="content"> <html> <head> <title><xsl:value-of select="nazev"/></title> </head> <body> <xsl:apply-imports/> <p align="center"><a href="katalog.html">Zpět</a></p> </body> </html> </xsl:variable> <!-- Uložíme si i jméno souboru --> <xsl:variable name="filename" select="concat(generate-id(.), '.html')"/> <!-- Otestujeme, zda bude zápis do souborů fungovat --> <xsl:if test="not(function-available('file:write'))"> <xsl:message terminate="yes"> Tento styl musíte zpracovat XSLT procesorem z MSXML. </xsl:message> </xsl:if> <xsl:value-of select="file:write($content, $filename)"/> </xsl:template> </xsl:stylesheet>