PHP : Function Reference : XSL functions : XSLTProcessor::registerPHPFunctions
XSLTProcessor {
void registerPHPFunctions(mixed restrict); }
This method enables the ability to use PHP functions as XSLT functions
within XSL stylesheets.
Parameters
- restrict
-
Use this parameter to only allow certain functions to be called from
XSLT.
This parameter can be either a string (a function name) or an array of
functions.
Return Values
No value is returned.
Examples
Example 2652. Simple PHP Function call from a stylesheet
<?php
$xml = <<<EOB <allusers>
<user>
<uid>bob</uid>
</user>
<user>
<uid>joe</uid>
</user>
</allusers> EOB; $xsl = <<<EOB <?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" encoding="utf-8" indent="yes"/>
<xsl:template match="allusers">
<html><body>
<h2>Users</h2>
<table>
<xsl:for-each select="user">
<tr><td>
<xsl:value-of
select="php:function('ucfirst',string(uid))"/>
</td></tr>
</xsl:for-each>
</table>
</body></html>
</xsl:template>
</xsl:stylesheet> EOB; $xmldoc = DOMDocument::loadXML($xml); $xsldoc = DOMDocument::loadXML($xsl);
$proc = new XSLTProcessor(); $proc->registerPHPFunctions(); $proc->importStyleSheet($xsldoc);
echo $proc->transformToXML($xmldoc); ?>
benbarnett
You can use the php:functionString() in the XSL, which will automatically convert output to a string!
heinemann dot juergen
You can find mor Examples at PHP Sources php-5.*/ext/xsl/tests
<?php
$xform = <<<EOT
<?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:extension-element-prefixes="php"
>
<xsl:output method="xml" indent="yes" encoding="utf-8" />
<xsl:namespace-alias stylesheet-prefix="php" result-prefix="xsl" />
<xsl:template match="root">
<html>
<head>
<title>Dateformat</title>
</head>
<body>
<xsl:for-each select="datenode">
<li>
<xsl:value-of select="php:functionString('convertDate', . )" />
</li>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
EOT;
function convertDate( $i )
{
setlocale( LC_TIME, 'de_DE' );
return utf8_encode( strftime( '%B %d %A %Y %H:%M:%S CET', $i ) );
}
$xsl = new XSLTProcessor;
$xsl->registerPHPFunctions();
$xsl->setParameter( 'DOCTYPE', 'PUBLIC', 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd' );
$xsl->setParameter( 'html', 'xmlns', 'http://www.w3.org/1999/xhtml' );
$xdom = new DomDocument( '1.0', 'utf-8' );
$xdom->loadXML( $xform );
$xsl->importStyleSheet( $xdom );
unset( $xdom );
$dom = new DomDocument( '1.0', 'utf-8' );
$r = $dom->appendChild( $dom->createElement( 'root' ) );
foreach ( range( 1, 12 ) AS $i ) {
$r->appendChild( $dom->createElement( 'datenode', mktime( date('G'), date('i'), date('s'), $i, date('d'), date('Y') ) ) );
}
header( "Content-Type: text/html; charset=utf-8;" );
header( "Content-Encoding: utf-8" );
echo $xsl->transformToXML( $dom );
?>
junkmail
ingram
Upon testing returning of a nodeset contributed by
taylorbarstow at that google mail thingy
(which works excellently, TY!)
I found that with using:
===
"Presumably, it's worth creating a template to do the discard:
<xsl:template select="*" mode="discardRoot">
<xsl:apply-templates select="./*" />
</xsl:template>
Which you can call like so:
<xsl:apply-templates select="php:function('getNodeSet')" mode="discardRoot" /> "
===
I could only output the text and not any of the tags after applying templates - i.e. it stripped all elements around text.
Instead using:
===
<xsl:template match="/">
<xsl:for-each select="php:function('getNodeSet')" />
<xsl:apply-templates />
</xsl:for-each>
</xsl:template>
which effectively discards the root node.
===
Worked fine and allowed me to apply-templates without problem on the returned nodeset.
thsoft
mark
Ritch said "If you wish to use a function from inside a class use the double colon (::) notation..." This worked in 5.0.4 but no longer works in 5.1.6.
zac
One thing to note about this function. A lot of values need to be converted to a XSLT string using the "string()" function in XLS before you pass them to your functions, and when you return them make sure that if they are strings that you call the "strval()" in php before doing so. This saved me hours.
Hope that helps.
Zac Bowling
hopeseekr
One of the peskiest things I had problems with was encoding URL parameters. I mean, pretend you want to populate a link with "search+terms" instead of just "search terms". I was including two seperate URLs in the XML and that was ludicrous.
Below is a far more elegant PHP+XSLT solution. You will also see it uses two *undocumented* features of registerPHPFunctions(), namely php:functionString() and the passing of parameters to the function. I figured this out by trial and error; I really hope this note helps you as it *greatly* expands the power of php functions in XSLT!
<?php
/* --- XML input --- */
<search_results>
<query>concert tickets</query>
</search_results>
/* --- XSL code --- */
<!-- Display query -->
<xsl:template match="search_results">
<!-- Get URL-encoded string via PHP -->
<xsl:variable name="safeurl" as="xs:string" select="php:functionString('urlencode', query)" />
Your search for <em><xsl:value-of select="query"/></em> can be continued at <a href="http://www.tixtix.com/search.php?q={$safeurl}">our search engine</a>
</xsl:template>
/* --- XHTML output --- */
Your search for <em>concert tickets</em> can be continued at <a href="http://www.tixtix.com/search.php?q=space+cowboy">our search engine</a>
?>
Cool, huh?
franp
Note that if you want your output to validate against some xhtml dtd, you must add the following attribute to the xsl:stylesheet element of the xslt stylesheet :
exclude-result-prefixes="php".
Otherwise, you get an "invalid attribute xmlns:php" error.
phil
Not true
Use :: to call static functions
Use -> to call non static functions
You must define a function as static in php 5.1 to be able to call it statically.
ritch
If you wish to use a function from inside a class use the double colon (::) notation, for example;
php:functionString('classname::function')
The funtion is fired off as a static and as such acts like a function in the global namespace.
begemot
I think it help your.
<?php
function dateLang () {
return strftime("%A");
}
$xsl = new DomDocument();
$xsl->load("datetime.xsl");
$inputdom = new DomDocument();
$inputdom->load("today.xml");
$proc = new XsltProcessor();
$proc->registerPhpFunctions();
// Load the documents and process using $xslt
$xsl = $proc->importStylesheet($xsl);
/* transform and output the xml document */
$newdom = $proc->transformToDoc($inputdom);
print $newdom->saveXML();
?>
Here's the XSLT stylesheet, datetime.xsl, that will call that function:
<?xml version="1.0" encoding="iso-8859-1" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">
<xsl:template match="/">
<xsl:value-of select="php:function('dateLang')" />
</xsl:template>
</xsl:stylesheet>
And here's an absolute minimal XML file, today.xml, to pass through the stylesheet (although articles.xml would achieve the same result):
<?xml version="1.0" encoding="iso-8859-1" ?>
<today></today>
taylorbarstow
From a PHP function, you can pass a nodeset back to XSL using a DOMDocument. For example:
<?php
function getNodeSet() {
$xml =
"<test>" .
"<a-node>This is a node</a-node>" .
"<a-node>This is another node</a-node>" .
"</test>";
$doc = new DOMDocument;
$doc->loadXml($xml);
return $doc;
}
?>
The only problem I've found is that the root level node in your returned DOM document acts like the root level node of your original. SO, it's easy to introduce an infinite loop like so:
<xsl:template match="/">
<xsl:apply-templates select="php:function('getNodeSet')" />
</xsl:template>
To avoid this, I've been using a construct like:
<xsl:template match="/">
<xsl:for-each select="php:function('getNodeSet')" />
<xsl:apply-templates />
</xsl:for-each>
</xsl:template>
which effectively discards the root node. Presumably, it's worth creating a template to do the discard:
<xsl:template select="*" mode="discardRoot">
<xsl:apply-templates select="./*" />
</xsl:template>
Which you can call like so:
<xsl:apply-templates select="php:function('getNodeSet')" mode="discardRoot" />
|
|