PHP Conference Japan 2024

XSLTProcessor::transformToXml

(PHP 5, PHP 7, PHP 8)

XSLTProcessor::transformToXml转换为 XML

描述

public XSLTProcessor::transformToXml(对象 $document): 字符串||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 个注释

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" />
lsoethout at hotmail dot com
18 年前
transformToXML 函数在 meta 内容类型标签方面存在问题。它输出如下

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

这不是正确的 X(HT)ML,因为它以 '>' 而不是 '/>' 结束。

获得正确输出的一种方法是使用 transformToDoc 而不是 transformToXML,然后保存 HTML

$domTranObj = $xslProcessor->transformToDoc($domXmlObj);
$domHtmlText = $domTranObj->saveHTML();
Charlie Murder
15 年前
为了防止您的 xsl 文件自动添加

<?xml version="1.0"?>

同时保持输出为 xml,这对于经过验证的严格 xhtml 文件来说是比较好的,而不是指定输出为

<xsl:output method="xml" omit-xml-declaration="yes" />
michael dot weibel at tilllate dot com
15 年前
如果从 transformToXML 方法检索到 "false",请使用 libxml_get_last_error() 或 libxml_get_errors() 来检索错误。
john
16 年前
如果您的 xsl 没有 <html> 标记。输出将包含 <?xml version="1.0"?>。要解决此问题,您可以在 xsl 样式表中添加以下内容

<xsl:output
method="html" />
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); // 伪装传入 loadXML() 的 &
$dom->substituteEntities = true; // 压缩传出 transformToXML() 的 &
$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); // 转换数据
?>
Josef Hornych
9 年前
请注意,该方法的名称有点误导性,因为它不仅输出 XML,还输出处理器生成的任何字符串。它应该更名为 transformToString。因此,例如,如果您的输出方法是“text/plain”,则可以通过这种方式接收结果字符串。
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();
smubldg4 at hotmail dot com
17 年前
如何修复:: *致命错误:调用未定义的方法 domdocument::load()*

如果遇到此错误,请访问 php.ini 文件并尝试注释掉以下内容,如下所示

;[PHP_DOMXML]
;extension=php_domxml.dll

突然,上面这个非常简单的例子按预期工作了。
Thomas Praxl
17 年前
我注意到 libxslt (php4) 和通过 XSLTProcessor 进行转换之间存在不兼容性。
Php5 和 XSLTProcessor 似乎添加了隐式的 CDATA-Section-Elements。
如果你的 xslt 像这样

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

它将产生

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

(至少对于 output method="xml" 来说,为了使用 xslt1 生成严格的 xhtml)

这会导致(至少)Firefox 1.5 中出现错误,因为它不是有效的 javascript。
它应该看起来像这样

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

由于 CDATA-Section 是隐式的,因此我无法禁用输出或在它前面放置“//”。

我尝试了所有关于 xsl:text disable-output-escaping="yes" 的内容

我还尝试使用 <output cdata-section-elements="" /> 禁用隐式添加 CDATA
(我以为这会排除 script-tags。但事实并非如此)。

解决方案

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

很简单,但花了我一段时间。
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 文件中使用的类名,并手动将其更改为正确的 casing。

另一个解决方案显然是使用全小写的类名和文件名。
To Top