©
このドキュメントでは、 php中国語ネットマニュアル リリース
(PHP 5 >= 5.0.4)
XSLTProcessor::registerPHPFunctions — Enables the ability to use PHP functions as XSLT functions
$restrict
] )This method enables the ability to use PHP functions as XSLT functions within XSL stylesheets.
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.
没有返回值。
Example #1 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 );
?>
版本 | 说明 |
---|---|
5.1.0 |
The restrict parameter was added.
|
[#1] Matthew, info at mathias-schaefer dot de [2010-11-25 08:34:06]
=> there is no instance of your class needed, you have to take care about the namespace (using 5.3).
<!-- xsl:
<xsl:value-of select="php:function ('My\Name\Space\MyClassName::methodName',1+2)"/>
--->
<?php
namespace My\Name\Space;
class MyClassName
{
static public function methodName($someArgument)
{
return "resultis:".$someArgument;
}
}
?>
<!-- result:
resultis:3
-->
=> no to-string conversion of the argument needed
=> returning numbers is also possible (maybe DOM nodes too)
Keep on hackin'
[#2] Demerit [2010-08-10 07:58:40]
Let's get the terminology correct here, folks.
If you are calling a function that is residing within a class, reference it by its INSTANCE name, NOT its class name.
class.my_class.php:
<?php
class class_name {
static function function_name($in){
return ($out);
}
}
?>
calling_document.php:
<?php
require_once('class.my_class.php');
$instance_name=new class_name();
?>
my_xslt.xsl:
<xsl:value-of select="php:function ('instance_name::function_name','garbage')" />
BTW, in 5.1.6 double-colon (::) is the only thing that works when calling a function that resides within a class. However, you must declare your function as static. Using -> as some have suggested (e.g., php:function ('instance_name->function_name','garbage')) doesn't work at all, no matter how you declare your function.
[#3] Nic Luciano [2009-07-22 11:09:26]
Ritch said "If you wish to use a function from inside a class use the double colon (::) notation..."
Also note that the class function must be declared as static.
[#4] Ariz Jacinto [2008-07-08 14:21:23]
If you want to use replace() function similar to XPath 2.0[1] and you want to avoid a long XSLT function similar to this one[2], you can use PHP's str_replace() instead:
<xsl:value-of select="php:functionString('str_replace','pattern', 'replacement' , . )">
Links:
[1] http://www.w3.org/TR/2004/WD-xpath-functions-20041029/#func-replace
[2] http://aspn.activestate.com/ASPN/Cookbook/XSLT/Recipe/65426
_
[#5] thsoft at vipmail dot hu [2007-12-27 14:22:17]
Unfortunately, you can't pass arrays to PHP from XLST.
But you can pass an arbitrary number of arguments to a PHP function and then get them with func_get_args() as an array.
[There's no sense writing a function that is identical to the array() construct, because a function's return value is converted to a string when passed as an argument to another function. This means deep arrays cannot be handled this way.]
[#6] thsoft at vipmail dot hu [2007-01-31 15:20:18]
The correct way to receive DOM nodes (let it be element, document, document fragment etc.) returned from PHP is to use <xsl:copy-of select="php:function...
I found the idea and an example here: http://bugs.php.net/bug.php?id=29409
For the technical details about the reason, see http://www.w3.org/TR/xslt#copy-of
[#7] phil at worldpoolfederation dot com [2006-12-01 03:22:48]
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.
[#8] mark at thirst dot org [2006-10-10 19:25:59]
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.
[#9] franp at free dot fr [2006-09-02 13:45:47]
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.
[#10] taylorbarstow at that google mail thingy [2006-05-26 05:33:05]
Add-on to my previous note (below) about returning nodesets to XSLT from PHP functions:
You don't have to return a DOMDocument, DOMElement works just as well. Plus, retuning a DOMElement gets around the problem of discarding the root node which I discuss below and which is also touched on by "Ingram".
[#11] heinemann dot juergen at hjcms dot de [2006-03-08 14:23:07]
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 );
?>
[#12] Ingram [2006-02-28 12:33:56]
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=".
<search_results>
<query>concert tickets</query>
</search_results>
<!-- 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)" />
<p>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></p>
</xsl:template>
<p>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></p>
?>
Cool, huh?
[#14] taylorbarstow at that google mail thingy [2005-12-01 07:14:07]
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=".
$newdom = $proc->transformToDoc($inputdom);
print $newdom->saveXML();
?>
Here's the XSLT stylesheet, datetime.xsl, that will call that function:
<?phpxml 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):
<?phpxml version="1.0" encoding="iso-8859-1" ?>
<today></today>
[#20] zac at zacbowling dot com [2004-08-26 21:48:41]
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