by Alexandre Alapetite on 2004-09-12; updated on 2008-11-01

XSL transition from PHP4 xslt to PHP5 xsl

When moving from PHP4 to PHP5, some modifications are required in the scripts. In PHP4, the experimental xslt extension was used to manage XSL, but this has been replaced by the experimental xsl extension in PHP5.

Migration from PHP4 to PHP5 is not that hard, but might be long if xslt was broadly used. Moreover, in order to have a smooth transition, it is good for scripts to be compatible with PHP5 as soon as possible, even if the server is still running PHP4. The optimisation for PHP5 can be done later.

I propose on this page a module (wrapper) to include in your PHP4/XSLT scripts, for them to be quite compatible with PHP5/XSL.

For DOMXML/DOM, have a look to my PHP4/DOMXML to PHP5/DOM page.

français

Table of contents

Exit

Scripts for PHP4 xslt compatible with PHP5 xsl

In order to run your PHP4 scripts that use xslt on a server moving to PHP5, you only need to include the file xslt-php4-to-php5.php in your PHP4 source code, this way:

if ((PHP_VERSION>='5')&&extension_loaded('xsl'))
 require_once('xslt-php4-to-php5.php');

Note that it does not modify your scripts when the server is still running PHP4.
It is covering only the main xslt functions, and not all of them. Nevertheless, it can be extended if needed.
Bellow, an example and the code for the compatibility file.

exemple-php4.php

<?php
//PHP4 script using xslt extension
//We want to make it run on PHP5 with xsl
if ((PHP_VERSION>='5')&&extension_loaded('xsl'))
 require_once('xslt-php4-to-php5.php'); //Load the PHP5 converter

$xml='<?xml version="1.0" encoding="ISO-8859-1"?>
<myRoot>
 <myNode/>
 <myNode/>
</myRoot>';

$xsl='<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="xml" version="1.0" encoding="ISO-8859-1" omit-xml-declaration="no" indent="yes"/>
 <xsl:param name="myParam"/>
 <xsl:template match="/">
  <myRoot2>
   Transformation
   <xsl:apply-templates select="/myRoot/myNode"/>
  </myRoot2>
 </xsl:template>
 <xsl:template match="/myRoot/myNode">
  <myNode>
   <xsl:attribute name="value">
    <xsl:value-of select="$myParam"/>
   </xsl:attribute>
  </myNode>
 </xsl:template>
</xsl:stylesheet>';

$xh=xslt_create();

echo xslt_process($xh,'arg:/_xml','arg:/_xsl',null,
 array('/_xml'=>$xml,'/_xsl'=>$xsl),
 array('myParam'=>'My parameter value'));

/*Output:
<?xml version="1.0" encoding="ISO-8859-1"?>
<myRoot2>
 Transformation
 <myNode value="My parameter value"/>
 <myNode value="My parameter value"/>
</myRoot2>
*/
?>
xslt-php4-to-php5.php

<?php
/*
 Require PHP5, uses included XSL extension (to be enabled).
 To be used in PHP4 scripts using XSLT extension.
 Allows PHP4/XSLT scripts to run on PHP5/XSL
*/

$xslArgs=null; //Warning: only one XSLT object at a time
function xslt_create() {return new xsltprocessor();}
function xslt_errno($xh) {return 7;}
function xslt_error($xh) {return '?';}
function xslt_fetch_result($xslt_handle,$buffer_name=null)
{
 global $xslArgs;
 if (empty($buffer_name)) return $xslArgs['/_result'];
 elseif (substr($buffer_name,0,5)==='arg:/') $buffer_name=substr($buffer_name,5);
 if (isset($xslArgs['/'.$buffer_name])) return $xslArgs['/'.$buffer_name];
 elseif (isset($xslArgs[$buffer_name])) return $xslArgs[$buffer_name];
 else return '';
}
function xslt_free($xh) {unset($xh);}
function xslt_process($xh,$xmlcontainer,$xslcontainer,$resultcontainer=null,$arguments=array(),$parameters=array())
{ //See also: https://alexandre.alapetite.fr/doc-alex/domxml-php4-php5/
 //Based on: http://www.php.net/manual/book.xsl.php#45415
 $xml=new DOMDocument();
 $basedir=$xh->getParameter('sablotron','xslt_base_dir');
 if ($basedir && ($workdir=getcwd())) chdir($basedir);
 if (substr($xmlcontainer,0,5)==='arg:/')
 {
  $arg=substr($xmlcontainer,5);
  if (isset($arguments['/'.$arg])) $xml->loadXML($arguments['/'.$arg]);
  elseif (isset($arguments[$arg])) $xml->loadXML($arguments[$arg]);
 }
 else $xml->load($xmlcontainer);
 $xsl=new DOMDocument();
 if (substr($xslcontainer,0,5)==='arg:/')
 {
  $arg=substr($xslcontainer,5);
  if (isset($arguments['/'.$arg])) $xsl_=&$arguments['/'.$arg];
  elseif (isset($arguments[$arg])) $xsl_=&$arguments[$arg];
  else $xsl_='';
 }
 else $xsl_=file_get_contents($xslcontainer);
 $xsl->loadXML(str_replace('arg:/','arg://',$xsl_));
 $xh->importStyleSheet($xsl);
 global $xslArgs;
 $xslArgs=$arguments;
 if ($parameters!=null)
  foreach ($parameters as $param=>$value)
   $xh->setParameter('',$param,$value);
 $result=$xh->transformToXML($xml);
 if (isset($resultcontainer))
 {
  if (substr($resultcontainer,0,4)==='arg:') $xslArgs[substr($resultcontainer,4)]=$result;
  else file_put_contents($resultcontainer,$result);
 }
 if ($basedir && $workdir) chdir($workdir);
 if (isset($resultcontainer)) return true;
 else return $result;
}
function xslt_run($xh,$xslt_file,$xml_data_file,$result=null,$xslt_params=array(),$xslt_args=array()) {return xslt_process($xh,$xml_data_file,$xslt_file,$result==null?'arg:/_result':$result,$xslt_args,$xslt_params);}
function xslt_set_base($xh,$base) {$xh->setParameter('sablotron','xslt_base_dir',str_replace('file://','',$base));}
function xslt_set_encoding($xh,$encoding) {$xh->setParameter('sablotron','xslt_encoding',$encoding);} //Does nothing? So manual encoding, or use xsl:output @encoding in XSL document
function xslt_set_error_handler($xh,$handler) {}

class xslt_arg_stream
{
 public $position;
 private $xslArg;
 function stream_eof() {return $this->position>=strlen($this->xslArg);}
 function stream_open($path,$mode,$options,&$opened_path)
 {
  $this->position=0;
  $url=parse_url($path);
  $varname=$url['host'];
  global $xslArgs;
  if (isset($xslArgs['/'.$varname])) $this->xslArg=&$xslArgs['/'.$varname];
  elseif (isset($xslArgs[$varname])) $this->xslArg=&$xslArgs[$varname];
  else return false;
  return true;
 }
 function stream_read($count)
 {
  $ret=substr($this->xslArg,$this->position,$count);
  $this->position+=strlen($ret);
  return $ret;
 }
 function stream_tell() {return $this->position;}
 function url_stat() {return array();}
}

stream_wrapper_register('arg','xslt_arg_stream');
?>

History

0.6 2008-11-01
Added: xslt_fetch_result(), xslt_run() (compatibility PHP 4.0.3 to 4.0.6)
Modified: the name of the arguments passed by arg:/test can then be referenced with or without slash (/test or test)
0.5 2006-08-06
corrected: class attribute declaration with PHP5 object syntax. E_STRICT compliant
Added: xslt_set_encoding() but without any effect
0.4 2005-08-28
Added : xslt_set_base()
0.3.1 2004-10-29
Creative Commons Licence, French version "CC BY-SA (FR)"
0.3 2004-10-30
Corrected: file:// protocol. (Tested PHP 5.0.2)
2004-09-15
Added : domxml_xslt in the PHP4/DOMXML to PHP5/DOM library.
0.2 2004-09-13
Corrected: file:// protocol
0.1 2004-09-12
Initial release

Licence

This content is protected by a licence Creative Commons Attribution-ShareAlike 2.0 France "BY-SA (FR)" [Creative Commons License]


Acknowledgements

I wish to thank the people who gave feedback; amoung them, especially:


Comments

object: View comments

https://alexandre.alapetite.fr

Back