2012-10-18 7 views
12

Ich frage mich, ob und wie es möglich ist, eine PHP-Userspace-Funktion mit dem XSLT-Prozessor zu registrieren, die in der Lage ist, nicht nur ein Array von Knoten zu nehmen, sondern es auch zurückzugeben?Wie filtert man einen ausgewählten Knotensatz mit einer PHP-Funktion?

Gerade jetzt klagt PHP über ein Array String-Konvertierung der gemeinsamen Einrichtung mit:

function all_but_first(array $nodes) {   
    array_shift($nodes); 
    shuffle($nodes); 
    return $nodes; 
}; 

$proc = new XSLTProcessor(); 
$proc->registerPHPFunctions(); 
$proc->importStylesheet($xslDoc); 
$buffer = $proc->transformToXML($xmlDoc); 

Die XMLDocument ($xmlDoc) kann zum Beispiel zur Transformation sein:

<p> 
    <name>Name-1</name> 
    <name>Name-2</name> 
    <name>Name-3</name> 
    <name>Name-4</name> 
</p> 

Im Sheet es heißt wie folgt:

<xsl:template name="listing"> 
    <xsl:apply-templates select="php:function('all_but_first', /p/name)"> 
    </xsl:apply-templates> 
</xsl:template> 

Der Hinweis ist t er folgenden:

Hinweis: Array String-Konvertierung

Ich verstehe nicht, warum, wenn die Funktion ein Array als Eingabe wird nicht in der Lage ist, ein Array als auch zurück?

Ich habe versucht, auch andere „Funktion“ Namen, wie ich es gesehen habe php:functionString ist aber alles bisher versucht (php:functionArray, php:functionSet und php:functionList) funktionierte nicht.

Im PHP-Handbuch ist geschrieben, dass ich eine andere DOMDocument mit Elementen zurückgeben kann, aber dann sind diese Elemente nicht mehr aus dem Originaldokument. Das ergibt für mich keinen Sinn.

+1

Ich habe eine längere Recherche darüber gemacht, und ich kam zu der gleichen Lösung wie im letzten Satz: Sie müssten ein anderes 'DOMDocument' von dieser Funktion zurückgeben. Aber dann wird es wieder bugly, weil ich gerade den Klartext und keine Knoten herausbekam. ('xsl: for-each' hat auch nicht geholfen) –

+0

@DanLee: Danke für die Rückmeldung. Ich versuche es mit einem Iterator, aber es ist auch keine Freude: * "Warnung: Ein PHP-Objekt kann nicht in eine XPath-Zeichenkette umgewandelt werden" * - dann [Ich habe einen Blick in die Quelle geworfen] (http: //lxr.sweon. net/php/http/source/ext/dom/xpath.C# L222) und es behandelt nur Objekte, die eine Instanz von DomNode sind - also alle xpaths von Knoten zu bekommen, sie zu vereinigen und die "echte" DomNodeList zurückzugeben hat nicht funktioniert entweder. Es ist ein Durcheinander :) Es ist wahrscheinlich empfehlenswert, ein Array von Dom-Knoten als Rückgabewert zuzulassen. – hakre

+0

Ich verlinkte die falsche Bibliothek, aber der Code ist identisch: http://lxr.sweon.net/php/http/source/ext/xsl/xsltprocessor.c#L331 – hakre

Antwort

3

Etwas, das für mich funktioniert, ist eine Instanz DOMDocumentFragment anstelle eines Arrays zurückgeben. Um es an Ihrem Beispiel zu versuchen, habe ich Ihre Eingabe als gespeichert. Dann machte ich foo.xslt wie folgt aussehen:

<xsl:stylesheet version="1.0" xmlns:xsl='http://www.w3.org/1999/XSL/Transform' 
     xmlns:php="http://php.net/xsl"> 
    <xsl:template match="/"> 
     <xsl:call-template name="listing" /> 
    </xsl:template> 
    <xsl:template match="name"> 
     <bar> <xsl:value-of select="text()" /> </bar> 
    </xsl:template> 
    <xsl:template name="listing"> 
     <foo> 
      <xsl:for-each select="php:function('all_but_first', /p/name)"> 
       <xsl:apply-templates /> 
      </xsl:for-each> 
     </foo> 
    </xsl:template> 
</xsl:stylesheet> 

(. Dies ist meist nur Ihr Beispiel mit einem xsl:stylesheet Wrapper um es aufzurufen) und das wahre Herz der Materie, foo.php:

<?php 

function all_but_first($nodes) { 
    if (($nodes == null) || (count($nodes) == 0)) { 
     return ''; // Not sure what the right "nothing" return value is 
    } 
    $returnValue = $nodes[0]->ownerDocument->createDocumentFragment(); 
    array_shift($nodes); 
    shuffle($nodes); 
    foreach ($nodes as $node) { 
     $returnValue->appendChild($node); 
    } 
    return $returnValue; 
}; 

$xslDoc = new SimpleXMLElement('./foo.xslt', 0, true); 
$xmlDoc = new SimpleXMLElement('./foo.xml', 0, true); 

$proc = new XSLTProcessor(); 
$proc->registerPHPFunctions(); 
$proc->importStylesheet($xslDoc); 
$buffer = $proc->transformToXML($xmlDoc); 
echo $buffer; 

?> 

Die wichtige Teil ist der Aufruf an ownerDocument->createDocumentFragment(), um das Objekt zu machen, das von der Funktion zurückgegeben wird.

+0

Ich war mir Ihrer Antwort bis jetzt nicht bewusst. Vielen Dank, das funktioniert wirklich :) - Großartig! – hakre

Verwandte Themen