2012-10-18 13 views
12

Mi chiedo se e come sia possibile registrare una funzione di spazio utente PHP con il processore XSLT che è in grado non solo di prendere una serie di nodi ma anche di restituirla?Come filtrare un nodeset selezionato con una funzione PHP?

In questo momento PHP lamenta una serie di conversione di stringa utilizzando l'impostazione comune:

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); 

XmlDocument ($xmlDoc) per trasformare la può ad esempio essere:

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

All'interno del foglio di stile si chiama così:

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

L'avviso è t egli segue:

Avviso: Array alla conversione stringa

Non capisco il motivo per cui se la funzione ottiene un array come ingresso non è in grado di restituire una matrice come bene?

cercavo anche altri nomi "funzione" come ho visto c'è php:functionString ma tutto ha provato finora (php:functionArray, php:functionSet e php:functionList) non ha funzionato.

Nel manuale PHP è scritto È possibile restituire altri DOMDocument contenenti elementi, tuttavia tali elementi non provengono più dal documento originale. Questo non ha molto senso per me.

+1

Ho fatto una ricerca più lunga su questo, e mi è venuta in mente la stessa soluzione, come indicato nell'ultima frase: avresti bisogno di restituire un altro 'DOMDocument' da questa funzione. Ma poi si infastidisce di nuovo, perché ho appena tirato fuori il testo normale e nessun nodo. ('xsl: for-each' non ha aiutato neanche) –

+0

@DanLee: Grazie per il feedback. Ho appena provato con un iteratore ma non è nemmeno una gioia: * "Attenzione: un oggetto PHP non può essere convertito in una stringa XPath" * - quindi [Ho dato un'occhiata alla fonte] (http: //lxr.sweon. net/php/http/source/ext/dom/xpath.C# L222) e gestisce solo oggetti che sono un'istanza di alcuni DomNode - quindi ottenere tutti gli xpath del nodo, unirli e restituire il "reale" DomNodeList non ha funzionato o. È un casino :) Probabilmente vale la pena di suggerire di permettere una matrice di dom node qui come valore di ritorno. – hakre

+0

Ho collegato la libreria sbagliata, ma il codice è identico: http://lxr.sweon.net/php/http/source/ext/xsl/xsltprocessor.c#L331 – hakre

risposta

3

Qualcosa che funzioni per me è restituire un'istanza di DOMDocumentFragment invece di un array. Quindi, per provarlo sul tuo esempio, ho salvato il tuo input come . Poi ho fatto foo.xslt simile a questa:

<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> 

(. Questo è per lo più solo il vostro esempio con un wrapper xsl:stylesheet per invocarlo) E il vero nocciolo della questione, 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; 

?> 

L'importante parte è la chiamata a ownerDocument->createDocumentFragment() per rendere l'oggetto che viene restituito dalla funzione.

+0

Non ero a conoscenza della tua risposta fino ad ora.Grazie mille, funziona davvero :) - Fantastico! – hakre

Problemi correlati