使用应用模板在 XSLT 输出中保留 和其他特殊字符
Posted
技术标签:
【中文标题】使用应用模板在 XSLT 输出中保留 和其他特殊字符【英文标题】:Keep and other special characters in XSLT output with apply-templates 【发布时间】:2012-09-16 18:27:27 【问题描述】:我正在使用 XSLT 从 XML 文件中提取一些带有特殊字符(如  
)的 html 内容。内容存储在<content>
节点中。我已经定义了像这样的大多数特殊字符:<!ENTITY nbsp "&#160;">
,所以这个表达式工作得很好:
<xsl:copy-of select="content" disable-output-escaping="yes"/>
现在,我想将target="_blank"
添加到该内容中的每个链接。这是我想出的解决方案:
<xsl:template match="a" mode="html">
<a>
<xsl:attribute name="href"><xsl:value-of select="@*"/></xsl:attribute>
<xsl:attribute name="target">_blank</xsl:attribute>
<xsl:apply-templates select="text()|* "/>
</a>
</xsl:template>
而不是“复制”元素,我使用这个:
<xsl:apply-templates select="content" mode="html"/>
现在所有这些特殊字符(以及 nbsp 也是)从输出中消失了。我该如何保留它们?似乎disable-output-escaping="yes"
在这里没有帮助。
好的,我在 php 中使用 XSLTProcessor 类。 disable-output-escaping
属性实际上并没有报错,但是当我删除它时,输出是一样的,所有 nbsp 的,所以没关系。
UPD。使用我之前展示的 XSL 模板,我的输入示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE page SYSTEM "html-entities.xsl">
<content>There is a non-breaking <a href="http://localhost">space</a> inside.</content>
html-entities.xsl:
<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY nbsp " ">
PHP 代码:
$xp = new XSLTProcessor();
$xsl = new DOMDocument();
$xsl->load($xsl_filename);
$xp->importStylesheet($xsl);
$xml_doc = new DOMDocument();
$xml_doc->resolveExternals = true;
$xml_doc->load($xml_filename);
$html = $xp->transformToXML($xml_doc);
我目前的输出:
There is anon-breaking <a href="http://localhost" target="_blank">space</a> inside.
我想要的输出:
There is a&nbsp;non-breaking <a href="http://localhost" target="_blank">space</a> inside.
【问题讨论】:
是否可以显示您的“内容”XML 示例?谢谢! 我在w3.org/TR/xslt20/#copy-of 中的copy-of
元素上看不到任何disable-output-escaping
属性,所以我希望您的代码示例<xsl:copy-of select="content" disable-output-escaping="yes"/>
只会由XSLT 处理器给出错误。考虑向我们展示有关输入样本、所需输出、当前输出和您使用的 XSLT 处理器的更多详细信息。
好的,我在 PHP 中使用 XSLTProcessor 类。 disable-output-escaping
属性实际上并没有报错,但是当我删除它时,输出是一样的。
更新了我的问题,请您的想法...
【参考方案1】:
基本上,输入 XML 文档的源代码是否具有像 &#160;
这样的字符引用或像 &nbsp;
这样的实体引用,或者这样的字符对于 XSLT 来说并不重要,也不会影响输入的处理方式以及输出的外观;基本上,XSLT 在一个树上运行,Unicode 字符存储在文本节点中。至少理论上是这样,您的 PHP 代码似乎可以与 DOM 树模型一起使用,该模型可能存储实体引用节点,但即便如此,对于 XSLT 来说也无关紧要。在输入树中应该有包含 Unicode 字符的文本节点(如果可能是 Unicode 160 的不间断空格字符),如果将这样的文本复制到输出,则结果树有一个文本节点具有相同的 Unicode 字符.
对于输出方法html
,一些 XSLT 处理器(例如 Saxon 6.5.5)可能会帮助您确保在 HTML 中定义为实体的字符使用相应的实体引用进行序列化,但即使它们不这样做结果树的序列化应该是具有正确 Unicode 字符的文件,按照xsl:output
元素的encoding
属性的指示进行编码。
您当前完全删除字符的结果(例如There is anon-breaking
)对我来说没有意义。
【讨论】:
您认为我的将target="_blank"
属性添加到链接的模板的编写方式正确吗?
我认为模板并不重要,因为不间断空格甚至不在 a
元素内,而是在兄弟文本节点内。如果我要写这样一个模板,我会使用<xsl:template match="a[@href]"><a target="_blank"><xsl:copy-of select="@*"/><xsl:apply-templates/></a></xsl:template>
。在您的尝试中,<xsl:attribute name="href"><xsl:value-of select="@*"/></xsl:attribute>
看起来很奇怪,因为它用@*
而不是@href
填充href
(并且@*
将采用当前实现在代码运行中认为第一个属性的值)。以上是关于使用应用模板在 XSLT 输出中保留 和其他特殊字符的主要内容,如果未能解决你的问题,请参考以下文章