PHP Conference Japan 2024

XSLTProcessor::transformToXml

(PHP 5, PHP 7, PHP 8)

XSLTProcessor::transformToXml轉換為 XML

描述

public XSLTProcessor::transformToXml(object $document): string|null|false

將來源節點轉換為字串,並套用 xsltprocessor::importStylesheet() 方法所提供的樣式表。

參數

document

要轉換的 DOMDocumentSimpleXMLElement 物件。

回傳值

轉換結果以字串形式傳回,若發生錯誤則傳回 false

範例

範例 #1 轉換為字串

<?php

// 載入 XML 來源
$xml = new DOMDocument;
$xml->load('collection.xml');

$xsl = new DOMDocument;
$xsl->load('collection.xsl');

// 設定轉換器
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl); // 附加 xsl 規則

echo $proc->transformToXML($xml);

?>

以上範例會輸出

Hey! Welcome to Nicolas Eliaszewicz's sweet CD collection!

<h1>Fight for your mind</h1><h2>by Ben Harper - 1995</h2><hr>
<h1>Electric Ladyland</h1><h2>by Jimi Hendrix - 1997</h2><hr>

參見

新增註解

使用者貢獻的註解 11 則註解

6
werner@mollentze
18 年前
transformToXML 函式可以產生有效的 XHTML 輸出 - 它會遵循 <xsl:output> 元素的屬性,這些屬性定義了輸出文件的格式。

例如,如果您想要有效的 XHTML 1.0 Strict 輸出,您可以在 XSL 樣式表中的 <xsl:output> 元素提供以下屬性值

<xsl:output
method="xml"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" />
5
lsoethout at hotmail dot com
18 年前
transformToXML 函式在 meta content type 標籤方面有問題。 它會輸出如下

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

這是不正確的 X(HT)ML,因為它是以 '>' 而非 '/>' 結尾。

要取得正確輸出的方法是,不要使用 transformToXML,而是先使用 transformToDoc,然後再使用 saveHTML

$domTranObj = $xslProcessor->transformToDoc($domXmlObj);
$domHtmlText = $domTranObj->saveHTML();
7
Charlie Murder
15 年前
為了防止您的 xsl 檔案自動在前面加上

<?xml version="1.0"?>

同時保持輸出為 xml(這對於經過驗證的嚴格 xhtml 檔案來說是較佳的),請明確指定輸出為

<xsl:output method="xml" omit-xml-declaration="yes" />
3
michael dot weibel at tilllate dot com
15 年前
如果您從 transformToXML 方法取得 "false",請使用 libxml_get_last_error() 或 libxml_get_errors() 來擷取錯誤。
3
john
16 年前
如果您的 xsl 沒有 <html> 標籤。 輸出將包含 <?xml version="1.0"?>。 若要修正此問題,您可以在 xsl 樣式表中新增以下內容

<xsl:output
method="html" />
6
zweibieren at yahoo dot com
14 年前
實體會從上面的程式碼輸出中省略。
症狀是 &nbsp;
-- 這應該能搭配 UTF-8 編碼運作 --
甚至沒有到達 XSLTProcessor,更不用說通過它了。
在過多的駭客攻擊後,我發現了簡單的修正方法
在 XSL 檔案的 DOMDocument 中,將 substituteEntities 設定為 true。
也就是說,將載入 xsl 文件替換為

<?php
$xsl
= new DOMDocument;
$xsl->substituteEntities = true; // <=== 加入的程式碼
$xsl->load('collection.xsl');
?>

但是,當資料項目包含 HTML 實體參考時,此方法會失敗。(有些資料庫項目甚至可能包含使用者產生的文字。)libxml 有對於任何未定義的實體擲回嚴重錯誤的迂腐習慣。 解決方法:隱藏實體,讓 libxml 看不到它們。

<?php
function hideEntities($data) {
return
str_replace("&", "&amp;", $data);
}
?>

您可以將此程式碼新增到範例中,但定義一個函式將資料載入 DOMDocument 中會比較整潔。 這樣您也不需要在 catalog.xsl 中加入實體宣告。

<?php
// 為範例 #1 加入的函式

/** 載入一個 XML 檔案並建立 DOMDocument。
處理任意實體,甚至是未定義的實體。
*/
function fileToDOMDoc($filename) {
$dom= new DOMDocument;
$xmldata = file_get_contents($filename);
$xmldata = str_replace("&", "&amp;", $xmldata); // 偽裝要載入 XML 的 & 符號
$dom->substituteEntities = true; // 折疊要轉換為 XML 的 & 符號
$dom->loadXML($xmldata);
return
$dom;
}

// 與範例 #1 轉換為字串比較

// 載入 XML 來源
$xml = fileToDOMDoc('collection.xml');
$xsl = fileToDOMDoc('collection.xsl');

// 設定轉換器
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);

// 根據樣式表 $xsl 轉換 $xml
echo $proc->transformToXML($xml); // 轉換資料
?>
3
Josef Hornych
9 年前
請注意,此方法名稱有點誤導,因為它不僅輸出 XML,還會輸出轉換器產生的任何字串。它應該更名為 transformToString。因此,如果您的輸出方法是 "text/plain",這就是接收結果字串的方式。
0
jeandenis dot boivin at gmail dot com
17 年前
$domTranObj = $xslProcessor->transformToDoc($domXmlObj);
$domHtmlText = $domTranObj->saveHTML();

請修正 <meta> 以符合有效的 XHTML,但不要正確結束像 <br /> 這樣的空節點,它會輸出像這樣:<br></br>。

有些瀏覽器會將此視為 2 個不同的 <br />...

若要修正此問題,請使用

$domTranObj = $xslProcessor->transformToDoc($domXmlObj);
$domHtmlText = $domTranObj->saveXML();
-1
smubldg4 at hotmail dot com
17 年前
如何修正:: *Fatal error: Call to undefined method domdocument::load()*

如果您收到此錯誤,請訪問 php.ini 檔案,並嘗試註解掉以下內容,如下所示

;[PHP_DOMXML]
;extension=php_domxml.dll

突然間,上面這個簡單的範例就如預期般運作了。
-2
Thomas Praxl
17 年前
我注意到 libxslt (php4) 與透過 XSLTProcessor 進行轉換之間存在不相容的問題。
Php5 和 XSLTProcessor 似乎會加入隱式的 CDATA 區段元素。
如果您的 xslt 如下

<script type="text/javascript">
foo('<xsl:value-of select="bar" />');
</script>

結果會變成

<script type="text/javascript"><![CDATA[
foo('xpath-result-of-bar');
]]></script>

(至少對於輸出方法為 "xml" 以便使用 xslt1 產生嚴格的 xhtml 來說)

這會在 Firefox 1.5 中產生錯誤(至少),因為它不是有效的 javascript。
它應該看起來像這樣

<script type="text/javascript">//<![CDATA[
foo('xpath-result-of-bar');
]]></script>

由於 CDATA 區段是隱式的,我無法停用輸出或在其前面放置 '//'。

我嘗試了所有關於 xsl:text disable-output-escaping="yes" 的方法

我也嘗試使用 <output cdata-section-elements="" /> 來停用隱式加入 CDATA 的功能
(我認為這會排除 script 標籤。但它沒有)。

解決方案

<xsl:text disable-output-escaping="yes">&lt;script type="text/javascript"&gt;
foo('</xsl:text><xsl:value-of select="bar" /><xsl:text disable-output-escaping="yes">');
&lt;/script&gt;</xsl:text>

很簡單,但花了我一段時間。
-2
jlipps at mac
19 年前
transformToXML,如果您先前已註冊 PHP 函數,當它在 php:function() 偽 XSL 函數中找到它們時,確實會嘗試執行這些函數。它甚至會找到類別中的靜態函數,例如

<xsl:value-of select="php:function('MyClass::MyFunction', string(@attr), string(.))" disable-output-escaping="yes"/>

但是,在這種情況下,transformToXML 不會嘗試執行 "MyClass::MyFunction()"。相反,它會執行 "myclass:myfunction()"。在 PHP 中,由於類別和函數(我認為)不區分大小寫,因此這不會造成任何問題。

當您將這些功能與 __autoload() 功能結合使用時,就會出現問題。因此,假設我有 MyClass.php,其中包含 MyFunction 定義。一般來說,如果我呼叫 MyClass::MyFunction,PHP 會將 "MyClass" 傳遞給 __autoload(),而 __autoload() 會開啟 "MyClass.php"。

然而,我們剛剛看到的意味著 transformToXML 會將 "myclass" 傳遞給 __autoload(),而不是 "MyClass",導致 PHP 嘗試開啟 "myclass.php",這不存在,而不是 "MyClass.php",它確實存在。在不區分大小寫的作業系統上,這並不重要,但在我的 RedHat 伺服器上,它是重要的 - PHP 會給出找不到檔案的錯誤。

我找到的唯一解決方案是編輯 __autoload() 函數,以尋找我的 XSL 檔案中使用的類別名稱,並手動將它們變更為正確的大小寫。

顯然,另一個解決方案是使用全部小寫的類別和檔案名稱。
To Top