2

I am using PHP with XSL and registerPHPfunctions.

It is ok for return PHP string values with xsl:value-of, but I not know how to return XML fragments from PHP.


Example at XSLT:

 <xsl:template match="table">
     <xsl:copy-of select="php:function('myfunc',.)"/>
 </xsl:template>

Example at PHP:

 function myfunc($x) {return '<table><tr><td>ok</td></tr></table>';}

Result is not XML but a "lt/gt/amp enconded XML". Use of copy-of or value-of at XSL, not modify the return behaviour. It is a cast problem?

PS: even with identity function, I tested, it not returns the XML node,

 function myfunc($x) {return $x;}
6
  • There is <xsl:value-of select="php:function('myfunc') disable-output-escaping="yes" /> for that. But to use it is considered bad practice - and its not working with PHP :| ( I tested with 5.3.10 Ubuntu 12.04). I would advice you to create the <xml> nodes in the xsl not in the php functions. But however I don't know your application needs Commented Mar 4, 2013 at 14:26
  • Hum... I try disable-output-escaping on my PHP environment and, also, not working... How to submit a "feature request" to PHP community? PHP not have XSLT2 or xQuery, so it is very important to PHP-XML users... Well, for my application I need to return nodes (not only string-values). Commented Mar 4, 2013 at 14:42
  • You could try to work with <xsl:if> for example to create the xml tree in xsl depending on the return value of a php function Commented Mar 4, 2013 at 14:52
  • Here is an existing feature request: bugs.php.net/bug.php?id=36156 Commented Mar 4, 2013 at 15:00
  • Possible related: How to filter a select nodeset with a PHP function? Commented Mar 5, 2013 at 11:18

2 Answers 2

2

Just return any subclass of DOMNode:

$xml = '<root/>';
$xsl = <<<'EOL'
<xsl:stylesheet version="1.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:php="http://php.net/xsl">
    <xsl:template match="/root">
        <xsl:copy-of select="php:function('myXMLFunc', .)"/>
    </xsl:template>
</xsl:stylesheet>
EOL;

function myXMLFunc($m) { // $m is always an array of DOMNodes
    $d = new DOMDocument();
    $e = $d->createElement('newroot');
    $e->appendChild($d->createTextNode('inner text'));
    return $e;
}

$xmldoc = DOMDocument::loadXML($xml);
$xsldoc = DOMDocument::loadXML($xsl);

$proc = new XSLTProcessor();
$proc->registerPHPFunctions('myXMLFunc');
$proc->importStyleSheet($xsldoc);

echo $proc->transformToXML($xmldoc);

The above will produce the xml <newroot>inner text</newroot>.

You can also construct your xml with SimpleXMLElement and convert to a DOM tree with dom_import_simplexml(), which you can then return. Using SimpleXML to construct xml is usually much less painful.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks a lot (!), yor method is "more DOM-explicit". Now and I am studing and comparing (the simplest!) solutions... And I'm curious about identity function: how to return $m in your myXMLFunc($m) function? (and where you see good documentation or tutorials about all this subject?)
The argument to the php function is always an array (representing a nodeset). You can do return $m[0]. A generic identity function is not possible, since the return value must always be either a single DOMNode (or subclass) or something that can be coerced to a string. It does not seem possible to return a nodeset, or at least the obvious ways (array or DOMNodeList) don't work. You can emulate nodesets with a container element, but you must discard it on the XSLT side.
A note, this feature (exposing php methods to xslt) is poorly documented and poorly supported, and has much ugliness about it. Rely on it as little as possible.
0

OPS, it is some kind of magic! Now the @hek2mgi tip is working!

I am using

 <xsl:template match="table">
  <xsl:copy-of select="php:function('myfunc',.)" disable-output-escaping="yes" />
 </xsl:template>

...I will back here in some days to say something more about "stable solution" and conclusions...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.