PHP Programming/XSL/registerPHPFunctions

The XSLTProcessor::registerPHPFunctions method enables to use PHP (v5.0.4+) functions as XSLT-v1 functions. Is a XSLT/registerFunction facility for "XSLT parser called by PHP".

It is a XSLTProcessor feature for exposing PHP functions or methods to the XSLT script (processed by importStyleSheet method). Very important for PHP users, because PHP (and any libxml2-dependent) not have a XSLT-v2 engine, and part of this functional lack can be overcome by using registerPHPFunctions. But, even in 2013's, most programmers share of the opinion that

The objective of this chapter, a tutorial for use PHP functions with XSLT, is trying to change this "state of affairs".

NOTE: another functional complement is to use PHP support for EXSLT library (see See also [1], [2], [3] ... and other tips (not to be confused with libraries of functions with similar names). The Common Module is the most important to use with registerPHPFunctions, having full implementation in all XML parsers.


The XSLTProcessor call need some inicializations, so, we can encapsulate this initializations in a single function, that use XML data and a XSLT script as inputs, and print the XSLTProcessor result.

function XSL_transf($xml,$xsl) {
	$xmldoc = DOMDocument::loadXML($xml);
	$xsldoc = DOMDocument::loadXML($xsl);
	$proc = new XSLTProcessor;
	echo $proc->transformToXML($xmldoc);

For send a XSLT script to this XSL_transf function, the XSLT script must be a string, so we can use a inline declaration (see PHP's Nowdoc and Heredoc),

$xsl = <<<'EOB'
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl=""
  <xsl:template match="/">

Another way is get it from a file,


or even changing the XSL_transf,

function XSL_transf($xmlFile,$xslFile) {
	$xmldoc = DOMDocument::load($xml);
	$xsldoc = DOMDocument::load($xsl);
        ... remaining same code...


After <xsl:stylesheet version="1.0" ...> declaration you can change the default output by, p. example,

  <xsl:output method="text"/>

In the examples of this tutorial, use always the XML method,

  <xsl:output method="xml" encoding="utf-8" indent="yes"/>

and, for see all tags withou need to open source-code in the browser, start the PHP script with

  header("Content-Type: text/plain; charset=utf-8");

Using PHP functions with static XSLT

In a first overview of the "exposing PHP to XSLT" feature, we can ignore the XML input data, using the XSLT script as a static template.

XSL receiving external string values

Declare and use of a XSLT script with PHP function calls (see xsl:value-of), that import string values from PHP functions (direct or parametrized).

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl=""
     xmlns:php="" exclude-result-prefixes="php">

  <xsl:template match="/">
	PHP time=<xsl:value-of select="php:function('time')" />, 
	PHP rand=<xsl:value-of select="php:function('rand')" />,
	PHP rand(11,99)=<xsl:value-of select="php:function('rand',11,99)" />,
	PHP xsl_myF1=<xsl:value-of select="php:function('xsl_myF1_StrConstant')" />,
	PHP xsl_myF2(XX)=<xsl:value-of select="php:function('xsl_myF2_id','XX')" />.

The first two functions can be called without any parameter, the two last functions are user-declared:

  function xsl_myF1_StrConstant { return "123"; }
  function xsl_myF2_id($str) { return $str; }

XSL_transf RESULT:

  PHP time=1365869487, 
  PHP rand=1410713536,
  PHP rand(11,99)=20,
  PHP xsl_myF1=123,
  PHP xsl_myF2(XX)=XX.

XSL receiving external XML as string

The <xsl:value-of ... /> clause usually receives string values, but with the disable-output-escaping attribute, it can receive an entire XML fragment.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl=""
  <xsl:output method="xml" encoding="utf-8" indent="yes"/>
  <xsl:template match="/">
     PHP xsl_myF2('<someTag/>')=<xsl:value-of select="php:function('xsl_myF2_id','<someTag/>')" />
     PHP xsl_myF2('<someTag/>')=<xsl:value-of select="php:function('xsl_myF2_id','<someTag/>')" disable-output-escaping="yes"/>
     PHP xsl_myF3=<xsl:value-of select="php:function('xsl_myF1_XmlConstant')" disable-output-escaping="yes"/>


  function xsl_myF1_XmlConstant { 
      return '<aBigFragment> text <someTag val="123"/> text </aBigFragment>'; 

XSL_transf RESULT:

   PHP xsl_myF2=&lt;someTag/&gt;
   PHP xsl_myF2=<someTag/>
   PHP xsl_myF3=
        <aBigFragment> text <someTag val="123"/> text </aBigFragment>

XSL receiving external XML as DOMElement

All XSLTProcessor activities relies in DOMDocument manipulations, so, for best performance, it is better to send a DOMElement object instead of a string.

The clause <xsl:copy-of ... /> receives DOMElement or DOMDocument, and <xsl:for-each ...> receives DOMNodeList. So, if we have a PHP function that returns DOMDocument, we can use it.

  function xsl_myF4_DOMConstant {
      static $xdom = DOMDocument::loadXML('<t> foo <tt val="123"/> bar </t>');
      return $xdom; 

Calling xsl_myF4 into the XSLT script,

  <xsl:template match="/">
     PHP xsl_myF4=<xsl:copy-of select="php:function('xsl_myF4_DOMConstant')" />


 PHP xsl_myF4=<t> foo <tt val="123"/> bar </t>

XSL receiving external fragments

A common need is to handle DOM fragments, that is, a XML without root. In the exemple above, function xsl_myF4_DOMConstant we used <t> foo <tt val="123"/> bar </t>. If the return value of needle is only foo <tt val="123"/> bar the function must be changed to,

  function xsl_myF4b_DOMFrag {
    $dom = new DOMDocument;
    $tmp = $dom->createDocumentFragment;
    $tmp->appendXML(' <t> foo <tt val="123"/> bar </t> TEST'); 
    return $tmp;

but now, to call xsl_myF4b (into the XSLT script) is not the same thing that call xsl_myF4, now we need to change the XPath expression to refer to a set of nodes.

  <xsl:template match="/">
     PHP xsl_myF4b=<xsl:copy-of select="php:function('xsl_myF4b_DOMFrag')/node" />

NOTE: Might be an LibXML2 bug, see an explanation here.


 PHP xsl_myF4b= <t> foo <tt val="123"/> bar </t> TEST

Using PHP functions with dynamic XSLT

"Real life" templates use XML input data for output. Suppose the following XML:

 <user> <uid>bob</uid> </user>
 <user> <uid>joe</uid> </user>

XSL sending and receiving string values

To send an input node as string, you can use the XPath-v1.0 string function of the Core Function Library, that converts a node to a string. If the argument is a XML fragment (a node with more than a single value), the "cast to string" replaces tags by blank spaces.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl=""
 <xsl:output method="xml" encoding="utf-8" indent="yes"/>
 <xsl:template match="allusers">
	<xsl:for-each select="user"> <xsl:value-of select="position"/>:
	   myF2(uid)="<xsl:value-of select="php:function('xsl_myF2_id',string(uid))" />",
	   myF2(.)="<xsl:value-of select="php:function('xsl_myF2_id',string(.))" />",

XSL_transf RESULT:

           myF2(.)=" BOB textTest ",
           myF2(.)=" JOE ",

XSL-registeredFunction communicating by DOM

The most complete way for an XSLT script to send a node as PHP-function parameter, is by sending it without string casting. PHP function will recive as parameter an array of DOMElements, and PHP can send back a DOMElement to the XSLT script.

This is the identity function implemented with this "DOM communication":

function xsl_myF5_id($m) {  // $m is always an array
    $ele = $m[0];  // get_class($m[0])==DOMElement
    return $ele; // XSLT accepts only DOMElement or DOMDocument

Using this function in a loop over input nodes,

	<xsl:for-each select="user"> <xsl:value-of select="position"/>:
	   copy-of  myF5(uid)="<copy-of select="php:function('xsl_myF5_id', uid)" />",
	   value-of myF5(uid)="<xsl:value-of select="php:function('xsl_myF5_id', uid)" />",
	   copy-of  myF5(.)=<xsl:copy-of select="php:function('xsl_myF5_id', . )" />.

XSL_transf RESULT:

          copy-of  myF5(uid)="<uid>BOB</uid>",
          value-of myF5(uid)="BOB",
          copy-of  myF5(.)=<user> <uid>BOB</uid> textTest </user>.
          copy-of  myF5(uid)="<uid>JOE</uid>",
          value-of myF5(uid)="JOE",
          copy-of  myF5(.)=<user> <uid>JOE</uid> </user>.

Using for lists: a function like xsl_myF5_id can return NULL, producing no interferences. This can be useful for array (or database) composing, later retrieved to XSLT by another function.

XSLT global parameters

There are more than one way to transfer PHP variables into XSLT, as global parameters:

  • calling a php:function that returns the PHP value of the variable;
  • Using setparameter in the parser, to create real XSLT-variables from xsl:parameter declaration.
  • injecting a "parameter-XML" in the XML input.

The first is perhaps the better, but each has its pros and cons.

Parameter-specific user-functions

Comparing with setParamter (section below), a function have he advantage of carry XML-fragments (not only string values), but not is accessed by XSLT as an usual variable. Typical use at XSLT:

<xsl:value-of select="php:function('xsl_strParam','param1')" />

With something like at PHP:

function xsl_strParam($paramName) {global $PARAMS; return $PARAMS[$paramName];}

To return DOM fragments, see section of "XSL receiving external fragments".

Setting XSLT global parameters

Global parameters are defined on the stylesheet level:

  <xsl:stylesheet version="1.0" xmlns:xsl="">
    <xsl:param name="param1" select="'default-string1'"/>

They can have a default value, specified by the select statement. Global parameters can be used to pass values from external applications to the stylesheet.

TIP: you can use a XPath at select attribute, <xsl:param name="p1" select="."/>, so, take care to use "'string'" when it is not an XPath.

To use the XSLTProcessor::setParameter, rewrite XSL_transf, at the Preparing section:

function XSL_transf($xml,$xsl,$param1val) {
	$xmldoc = DOMDocument::loadXML($xml);
	$xsldoc = DOMDocument::loadXML($xsl);
	$proc = new XSLTProcessor;
        $proc->setParameter('', 'param1', $param1val); // add here, $param1val will overwrites 'default-string1'
	echo $proc->transformToXML($xmldoc);

XML injection as parameter

Another natural way to read external parameters, is as part of the XML input string. Some DTD-conventions must reviewed, some "array to XML" conventions adopted, and DOM once-insert or replace must processed by the main function (ex. the XSL_transf function above).

It is recommended when there are a lot of parameters or XML fragments. An exemple of use this strategy was the 2.0.2 version of smallest-php-xml-xsl-framework, and "state injection" made there.

Working with real-life applications


... See XSLT/Standard-registerFunctions ...

Versions and contexts where the examples runs

Please colabore with your tests:

  • PHP 5.3.10-1ubuntu3.6 (Zend Engine v2.3.0). All examples runs.

External links

  This article uses material from the Wikipedia page available here. It is released under the Creative Commons Attribution-Share-Alike License 3.0.



Connect with defaultLogic
What We've Done
Led Digital Marketing Efforts of Top 500 e-Retailers.
Worked with Top Brands at Leading Agencies.
Successfully Managed Over $50 million in Digital Ad Spend.
Developed Strategies and Processes that Enabled Brands to Grow During an Economic Downturn.
Taught Advanced Internet Marketing Strategies at the graduate level.

Manage research, learning and skills at defaultLogic. Create an account using LinkedIn or facebook to manage and organize your Digital Marketing and Technology knowledge. defaultLogic works like a shopping cart for information -- helping you to save, discuss and share.

Visit defaultLogic's partner sites below: : Music Genres | Musicians | Musical Instruments | Music Industry
NCR Works : Retail Banking | Restaurant Industry | Retail Industry | Hospitality Industry

  Contact Us