[由 nielsdos 编辑:从 PHP 8.4.0 开始,这不再正确]
如果值同时包含单引号和双引号,则不会设置参数。转换文档时会显示警告。
PHP Warning: XSLTProcessor::transformToXml(): 无法创建 XPath 表达式(字符串同时包含单引号和双引号)
(PHP 5, PHP 7, PHP 8)
XSLTProcessor::setParameter — 设置参数值
设置一个或多个参数的值,这些参数将在随后使用 XSLTProcessor 进行转换时使用。如果样式表中不存在该参数,则将忽略它。
namespace
XSLT 参数的命名空间 URI。
name
XSLT 参数的本地名称。
value
XSLT 参数的新值。
options
name => value
对的数组。
如果任何参数包含空字节,则抛出 ValueError。
版本 | 描述 |
---|---|
8.4.0 | 现在,如果任何参数包含空字节,则会抛出 ValueError,而不是静默截断。 |
8.4.0 | 现在可以设置包含单引号和双引号的参数值。在 PHP 8.4.0 之前,这会导致警告。 |
示例 #1 转换前更改所有者
<?php
$collections = array(
'Marc Rutkowski' => 'marc',
'Olivier Parmentier' => 'olivier'
);
$xsl = new DOMDocument;
$xsl->load('collection.xsl');
// 配置转换器
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl); // 附加 xsl 规则
foreach ($collections as $name => $file) {
// 加载 XML 源
$xml = new DOMDocument;
$xml->load('collection_' . $file . '.xml');
$proc->setParameter('', 'owner', $name);
$proc->transformToURI($xml, 'file:///tmp/' . $file . '.html');
}
?>
[由 nielsdos 编辑:从 PHP 8.4.0 开始,这不再正确]
如果值同时包含单引号和双引号,则不会设置参数。转换文档时会显示警告。
PHP Warning: XSLTProcessor::transformToXml(): 无法创建 XPath 表达式(字符串同时包含单引号和双引号)
请注意,除非知道参数的名称,否则无法从 XSLTProcessor 中删除参数,并且(据我所知)无法获取当前参数的列表。
这意味着,除非您对每个参数调用 XSLTProcessor->removeParameter(),否则您无法重用具有不同参数的 XSLTProcessor,而要执行此操作,您需要知道所有当前已设置参数的名称。
我遇到这个问题是因为我们正在缓存 XSLTProcessor 以供重用,它们正在根据幻像参数输出内容(它们仍然来自之前的用途)。
看来 heinemann 的用法不正确,无法达到预期的结果。
此方法的目的是更改 XSL 样式表中的全局 <xsl:param> 值,而不是更改任何其他元素的属性。<xsl:param> 基本上允许您设置一个样式表,该样式表可以从外部(无需修改原始 XSL 文件)进行自定义(例如来自 PHP)。
这是一个用法示例(将起作用)
样式表
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="print_something" select="defaultstring"/>
<xsl:template match="/mydoc">
<p style="color:red;">Printed parameter: <xsl:value-of select="$print_something"/></p>
</xsl:template>
</xsl:stylesheet>
脚本
<?php
$dom = new DOMDocument();
$xsl = new XSLTProcessor;
$xsl->setParameter( '', 'print_something', "Now I've overridden the default!");
$style = realpath( "./my_stylesheet.xslt" );
$dom->load($style);
$xsl->importStyleSheet($dom);
$dom->loadXML('<mydoc></mydoc>');
$out = $xsl->transformToXML( $dom );
var_dump( '<pre>',
htmlentities( $out, ENT_QUOTES, 'utf-8' ),
$xsl->getParameter('', 'print_something'),
'</pre>' );
?>
给出
string(5) "
"
string(143) "<?xml version="1.0"?>
<p style="color:red;">Printed parameter: Now I've overridden the default!</p>
"
string(32) "Now I've overridden the default!"
string(6) "
"
注意,目前添加命名空间将不起作用。目前唯一的选择是将第一个命名空间参数设置为空字符串(尽管您可以将带冒号的前缀添加到第二个名称参数中,以便为命名空间前缀的参数名称设置参数)。
参见 http://bugs.php.net/bug.php?id=30622
进一步研究后(参见 http://bugs.php.net/bug.php?id=41248),似乎是libxslt的不足,而不是PHP的问题,导致无法将DOMDocuments或DOMNodes作为参数传递。
我一直在尝试将DOMDocument对象作为参数传递,以便将大量数据填充到XML节点中,但似乎此函数无法做到这一点。我希望它能像.NET 2.0框架那样工作。(参见 http://msdn2.microsoft.com/en-us/library/
system.xml.xsl.xsltargumentlist.addparam.aspx)
但是,在查看PHP 5.2.1源代码`/php-5.2.1/ext/xsl/xsltprocessor.c`的604-650行后,似乎即使libxslt似乎支持它(参见 http://xmlsoft.org/XSLT/html/libxslt-variables.html
#xsltParseGlobalParam)
事实上,如果参数不完全符合预期,你将始终收到类似这样的警告:
XSLTProcessor::setParameter() 参数数量错误
工作示例。
<?xml version = '1.0' encoding = 'utf-8' ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"
indent="yes"
encoding="ISO-8859-15"
doctype-system = "-//W3C//DTD XHTML 1.0 Transitional//EN"
doctype-public = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
/>
<xsl:template match="docs">
<html>
<head>
<title>
<xsl:text>示例</xsl:text>
</title>
</head>
<body>
<xsl:for-each select="block">
<div>
<xsl:value-of select="." />
</div>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
------------------
<?php
$dom = new DomDocument( '1.0', 'utf-8' );
$xsl = new XSLTProcessor;
$xsl->setParameter( 'block', 'xmlns', 'http://www.w3.org/1999/xhtml' );
$style = realpath( "./my_stylesheet.xslt" );
$dom->load( $style );
$xsl->importStyleSheet( $dom );
$dom->loadXML( '<docs>
<block>如何在php中设置xhtml Transitional命名空间</block>
<block>参见https://php.net</block>
</docs>' );
$out = $xsl->transformToXML( $dom );
var_dump( '<pre>',
htmlentities( $out, ENT_QUOTES, 'utf-8' ),
$xsl->getParameter( 'block', 'xmlns' ),
$xsl->getParameter( 'docs', 'xmlns' ),
'</pre>' );
?>