<?php // ?>

praktyczne porady dotyczące programowania aplikacji internetowych

Jak używać transformacji XSLT w PHP

PHP -> XSLT -> XML -> XSLT -> XHTML

XSLT jest fajnym językiem, który może być z powodzeniem wykorzystany do generowania złożonych szablonów oddzielonych całkowicie od warstwy biznesowej serwisów internetowych. Po przeprowadzeniu eksperymentów, które na celu miały sprawdzenie jak to działa w praktyce wykorzystując pewien sposób udało mi się wyeliminować konieczność posiadania fizycznie zapisanego pliku XML, którego obecność dla prawidłowego działania transformacji XSLT jest niezbędna.

Trik polega na podwójnym parsowaniu dokumentu, dzięki któremu za pierwszym razem otrzymujemy XML, który istniejąc tylko jako zmienna tekstowa jest wykorzystywany do właściwego generowania XHTML'a! Jak to działa w praktyce weźmy na przykład taki oto XSLT. Plik posiada dwa zdefiniowany template'y jeden parsuje tag pre a drugi post.

index.xsl

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">
<xsl:output method="html" omit-xml-declaration="yes" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" indent="yes" />
   
    <!-- start pre process -->
    <xsl:template match="pre">
        <post>
            <xsl:value-of select="php:function('User::_get', string('name'))" />
        </post>
    </xsl:template>
    <!-- end pre process -->
   
    <!-- start post process -->
    <xsl:template match="post">
        <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pl">
            <body>
                <xsl:choose>
                    <xsl:when test="name = ''">
                        <form action="index.php" method="post">
                            <p>
                                <label for="input-name">Podaj swoje imię: </label>
                                <input name="input-name" id="input-name" type="text" />
                            </p>
                            <p>
                                <input value="Wyślij" type="submit" />
                            </p>
                        </form>
                    </xsl:when>
                    <xsl:otherwise>
                        <p>Witaj <xsl:value-of select="name" />!</p>
                    </xsl:otherwise>
                </xsl:choose>
            </body>
        </html>
    </xsl:template>
    <!-- end post process -->
   
</xsl:stylesheet>
<!-- created by Michal Luberda 2009 -->

W naszym przykładzie pre będzie prostym ciągiem znaków z zadeklarowanym pustym elementem i będzie przypisany bezpośrednio w kodzie PHP. W wyniku parsowania pierwszej części otrzymamy XML, którego zawartość będzie zawierała się w tagu post, tutaj wykorzystałem jedną funkcję, która przypisuje wartość pobraną z tablicy $_POST. Drugi etap parsowania pobierze dane z elementu post i odpowiednio je przetwarzając do XHTML'a wyświetli je na ekranie! Prawda, że proste.

index.php

<?php

    /**
     * XSLT Double Processor
     *
     * @version 1.0
     * @author  Michal Luberda <luberda@iap.pl>
     */
   
    // get $_POST value
    User :: _set ("name", $_POST["input-name"]);
   
    // read xsl template
    $id_file = @ fopen ("index.xsl", "r");
    $st_xsl  = "";
    while (! feof ($id_file)) {
        $st_xsl .= fread ($id_file, 4096);
    }
    fclose ($id_file);
   
    // pre process
    $ob_xml = new DOMDocument ("1.0", "utf-8");
    $ob_xml  -> loadXML ("<?xml version=\"1.0\" encoding=\"UTF-8\"?><pre></pre>");
   
    $ob_xsl  = new DOMDocument ("1.0", "utf-8");
    $ob_xsl -> loadXML ($st_xsl);
   
    $ob_xslp = new XSLTProcessor ();
    $ob_xslp -> registerPHPFunctions ("User::_get");
    $ob_xslp -> importStyleSheet ($ob_xsl);
   
    $st_xml = $ob_xslp -> transformToXML ($ob_xml);
   
    $st_xml = str_replace (
        array (
            "<post xmlns:php=\"http://php.net/xsl\">",
            "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">",
            "&lt;",
            "&gt;"
        ),
        array (
            "<post>",
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
            "<",
            ">"
        ),
        $st_xml
    );
   
    // post process
    $ob_xml = new DOMDocument ("1.0", "UTF-8");
    $ob_xml -> loadXML ($st_xml);
    $st_xml = $ob_xslp -> transformToXML ($ob_xml);
   
    // print result
    print $st_xml;
   
    // define user class
    class User
    {
        public static $ob;
       
        static public function _get ($st)
        {
            return
                "<" . $st . ">" .
                    (isset (self :: $ob -> $st) ? self :: $ob -> $st : "") .
                "</" . $st . ">";
        }
       
        static public function _set ($st, $value)
        {
            if (! is_object (self :: $ob))
                self :: $ob = new stdClass ();
            self :: $ob -> $st = $value;
        }
    }

?>

Całość do ściągnięcia tutaj: Transformacje XSLT w PHP

Wenecja 2009 opracowany przez Michał Luberda