XSLT Block Function

I wrote this block function for a client's site. They wanted to have Slashdot headlines on the site using Slashdot's XML stream. The block function accepts an XML document in the following formats: URL, file (prefixed by "file://", relative to current PHP file) or a variable name (any global variable). The XML is then transformed using the XSLT style captured within the block.

Included is support for my Cacher object; if it is not available in any include path, a dummy object is loaded.

Example usage:

{xslt xml="http://slashdot.org/slashdot.xml" cache="3600"}
<?xml version="1.0"?>
  <xsl:stylesheet version="1.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
  <xsl:output method="xhtml" encoding="iso-8859-1"/> 
  <xsl:template match="/backslash">
  <xsl:for-each select="story"> 
   <xsl:if test="position() &lt; 7"> :: 
     <a>
      <xsl:attribute name="target">_blank</xsl:attribute> 
      <xsl:attribute name="href"><xsl:value-of select="url"/></xsl:attribute> 
      <xsl:value-of select="title"/> 
     </a><br />
   </xsl:if> 
  </xsl:for-each> 
  </xsl:template> 
  </xsl:stylesheet> 
{/xslt}

- Serge

<?php
/*
 * Smarty plugin
 * -------------------------------------------------------------
 * File:     block.xslt.php
 * Type:     block
 * Name:     xslt
 * Purpose:  transform XML from variable using XSLT inside block
 * Params:  
 * * "xml" - either specify the name of a variable which contains
 *           the XML document, or specify a filename prefixed by
 *           "file://". eg., xml="file://document.xml"
 *           You could also do xml="http://someURL"
 * Requires: Sablatron and expat, Cacher object for caching support (optional)
 * Author:   Serge Stepanov (serge_at_gfxcafe_dot_com
 * -------------------------------------------------------------
 */
function smarty_block_xslt($params, $content, &$smarty)
{
    if ($content) {

	if (!function_exists("xslt_create")) {
	    echo "<strong>Smarty XSLT Module:</strong> XSLT Not Found"; 
	    return;
        }

        /*
         We will use the "xml" parameter passed to the block
         function as the name of a variable which contains the
         XML document, variable or URL.
        */
        $xmlVariable = trim($params['xml']);
        
        /* 
         Caching --
         If you have my Cacher object installed and wish to cache the
         result of your XSLT parsing, pass the "cache" variable to the
         block with the number of seconds you want to cache the result.
        */
        $cacheLength = trim($params['cache']);
        
        /* 
         Attempt to init Cacher, if the class doesn't exits or
         no caching is requested, init DummyObject
        */
        if ($cacheLength != 0 && class_exists("Cacher")) {
            $cache = new Cacher;
        } else {
            $cache = new DummyObject;
        }
        
        
        if ($cachedResult = $cache->Get($xmlVariable, $cacheLength)) {
            echo $cachedResult;
        } else {            
            /* 
             If the "xml" param starts with file://, load that file
             into the variable and continue.  
                
             If the the param starts with http://, load it as a 
             remote file.
                
             Otherwise, use the XML param
             as a variable name.
            */
            if (substr($xmlVariable, 0, 7) == "file://") {
                $fileName = substr($xmlVariable, 7);
                
                /* Check if file is available */
                if (!file_exists($fileName)) {
                    echo "<strong>Smarty XSLT Module:</strong> XML Not Found"; 
                    return;
                }
                
                $fileHandler = fopen($fileName, "r");
                $xmlSource = fread($fileHandler, filesize($fileName));	    
                fclose($fileHandler);            
            } else if (substr($xmlVariable, 0, 7) == "http://") {
                $fileHandler = fopen($xmlVariable, "r");
                while($buf = fgets($fileHandler,1024) ) {
                    $xmlSource .= $buf;
                }
            } else {
                global ${$xmlVariable};
                $xmlSource = ${$xmlVariable};            
            }
            
            /* Remove spaces */
            $xmlSource = trim($xmlSource);
            $xsltSource = trim($content);
            
            /* Create argument variable */
            $arguments = array(
                '/_xml' => $xmlSource,
                '/_xsl' => $xsltSource
            );
            
            /* Allocate XSLT processor */
            $xsltHandler = xslt_create();
            
            /* Process and return result */
            $result = xslt_process($xsltHandler, 'arg:/_xml', 'arg:/_xsl', NULL, $arguments);
            
            /* Print the result, or if an error occured, print the message */
            if (xslt_errno($xsltHandler)) {
                $result .= "<strong>Smarty XSLT Module:</strong> <br />";
                $result .= xslt_errno($xsltHandler) . "<br />";
                $result .= xslt_error($xsltHandler);
            }
            
            $cache->Set($xmlVariable, $result);            
            
            echo $result;
            
            /* Destroy XSLT processor */
            xslt_free($xsltHandler);
        }
    }
}

/* Dummy object for use incase cache is not available */
class DummyObject {
    function Get() {
        return false;
    }
    function Set() {
        return true;
    }
} 

?>