2012-10-18 28 views
12

Tôi tự hỏi liệu có thể đăng ký một hàm không gian người dùng PHP với bộ xử lý XSLT không chỉ có thể lấy một mảng các nút mà còn có thể trả về nó không?Làm thế nào để lọc một nút chọn một với một chức năng PHP?

Ngay bây giờ PHP phàn nàn về một mảng để chuyển đổi chuỗi bằng cách sử dụng thiết lập chung:

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) để chuyển đổi lon ví dụ là:

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

Trong stylesheet nó được gọi là như thế này:

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

Thông báo là t ông sau:

Thông báo: Array để chuyển đổi chuỗi

Tôi không hiểu tại sao nếu chức năng được một mảng như là đầu vào không có khả năng trả lại một mảng không?

Tôi cũng đang thử các tên "chức năng" khác như tôi đã thấy có php:functionString nhưng tất cả đã thử cho đến nay (php:functionArray, php:functionSetphp:functionList) không hoạt động.

Trong hướng dẫn sử dụng PHP được viết, tôi có thể trả về một phần tử khác có chứa DOMDocument, tuy nhiên các phần tử đó không còn từ tài liệu gốc nữa. Điều đó không có ý nghĩa với tôi.

+1

Tôi đã nghiên cứu lâu hơn về điều này và tôi đã đưa ra giải pháp tương tự như đã nêu trong câu cuối cùng: Bạn cần trả về một 'DOMDocument' khác từ hàm này. Nhưng sau đó nó lại bị lỗi một lần nữa, bởi vì tôi chỉ nhận được văn bản thuần túy và không có nút nào. ('xsl: for-each' không giúp được gì cả) –

+0

@DanLee: Cảm ơn bạn đã phản hồi. Chỉ cần thử với một trình lặp nhưng cũng không có niềm vui: * "Cảnh báo: Một đối tượng PHP không thể được chuyển đổi thành chuỗi XPath" * - sau đó [Tôi đã xem xét mã nguồn] (http: //lxr.sweon. net/php/http/source/ext/dom/xpath.C# L222) và nó chỉ xử lý đối tượng là một thể hiện của một số DomNode - vì vậy nhận được tất cả các nút xpath, liên kết chúng và trả về "real" DomNodeList không hoạt động hoặc. Đó là một mớ hỗn độn :) Có lẽ đáng để đề xuất cho phép một mảng các nút dom ở đây dưới dạng giá trị trả lại. – hakre

+0

Tôi đã liên kết thư viện sai, nhưng mã giống hệt nhau: http://lxr.sweon.net/php/http/source/ext/xsl/xsltprocessor.c#L331 – hakre

Trả lời

3

Điều gì đó phù hợp với tôi là trả lại phiên bản DOMDocumentFragment thay vì một mảng. Vì vậy, để thử nó trên ví dụ của bạn, tôi đã lưu đầu vào của bạn là . Sau đó, tôi làm foo.xslt trông như thế này:

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

(. Điều này chủ yếu chỉ là ví dụ của bạn với một wrapper xsl:stylesheet để gọi nó) Và trái tim thực sự của vấn đề, 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; 

?> 

Điều quan trọng một phần là cuộc gọi đến ownerDocument->createDocumentFragment() để làm cho đối tượng được trả về từ hàm.

+0

Tôi đã không nhận thức được câu trả lời của bạn cho đến bây giờ. Cảm ơn rất nhiều, điều này thực sự hoạt động :) - Tuyệt vời! – hakre

Các vấn đề liên quan