Potřebujete pomoci s XSLT?
Nabízím školení, konzultace, vývoj XSLT kódu na zakázku. Nevájte a kontaktujte mne.

Podpořte provoz stránek
Platba probíhá pomocí služby PayPal a je možné platit kartou nebo převodem z vašeho PayPal účtu.

12.3 Volání externích funkcí

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>&#xA;</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>

© Jiří Kosek 2014

Tento dokument je určen výhradně pro osobní potřebu seznámení s jazykem XSLT. Jakékoliv jiné použití, včetně dalšího šíření, pořizování kopií, použití při školeních a výuce apod. je výslovně zakázáno a bude považováno za porušení autorských práv.


Copyright © 2000-2014 Jiří Kosek