2012-10-18 42 views
12

我想知道是否以及如何用XSLT處理器註冊PHP用戶空間函數,該處理器不僅能夠獲取節點數組,還能夠返回它?如何使用PHP函數篩選選定的節點集?

現在PHP抱怨數組字符串轉換使用常用的設置:

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)來轉換例如可以是:

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

在它被稱爲樣式表像這樣:

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

該通知是t他以下幾點:

注意:數組字符串轉換

我不明白爲什麼當函數獲取一個數組作爲輸入無法返回數組中呢?

我也嘗試其他「功能」的名稱作爲我見過有php:functionString但到目前爲止(php:functionArrayphp:functionSetphp:functionList)都試圖沒有奏效。

在PHP手冊中,我可以返回另一個包含元素的DOMDocument,但是那些元素不再是原始文檔。這對我來說沒有多大意義。

+1

我對此做了更長時間的研究,並且提出了與最後一句中所述相同的解決方案:您需要從此函數返回另一個「DOMDocument」。但後來它又變得錯誤了,因爲我剛剛拿出純文本和沒有節點。 ('xsl:for-each'也沒有幫助) –

+0

@DanLee:感謝您的反饋。剛剛嘗試過使用迭代器,但它也不是快樂:*「警告:一個PHP對象不能轉換爲XPath字符串」* - 然後[我看了一下源代碼](http://lxr.sweon。 net/php/http/source/ext/dom/xpath.c#L222),它只處理一些DOMNode實例的對象 - 因此獲取所有節點的xpath,將它們合併並返回「真正的」DomNodeList不起作用無論是。這是一個混亂:)這可能是值得建議允許在這裏的dom節點數組作爲返回值。 – hakre

+0

我鏈接了錯誤的庫,但代碼完全相同:http://lxr.sweon.net/php/http/source/ext/xsl/xsltprocessor.c#L331 – hakre

回答

3

對我來說有些東西是返回一個DOMDocumentFragment而不是一個數組的實例。因此,以您的示例進行嘗試,我將您的輸入保存爲。這時我犯了foo.xslt這個樣子:

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

(這是大多隻是你的一個xsl:stylesheet包裝來調用它實施例)和問題的真正心臟,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; 

?> 

重要部分是調用ownerDocument->createDocumentFragment()來使從函數返回的對象。

+0

直到現在我還沒有意識到你的答案。非常感謝,這真的有用:) - 太好了! – hakre