使用apply-templates在XSLT输出中保留" "和其他特殊字符

4

我正在使用XSLT从XML文件中提取一些带有特殊字符(如&nbsp;)的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>

我使用这个元素替代了"copy-of"元素:

<xsl:apply-templates select="content" mode="html"/>

现在所有特殊字符(包括空格)都消失了,我该如何保留它们?似乎disable-output-escaping="yes"也没用。
好的,我在PHP中使用XSLTProcessor类。实际上disable-output-escaping属性没有报错,但是当我将其删除时,输出结果相同,包含所有空格,所以这个属性并不重要。
更新。使用我之前展示的XSL模板和输入样本:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE page SYSTEM "html-entities.xsl">
<content>There is a&nbsp;non-breaking <a href="http://localhost">space</a> inside.</content>

html-entities.xsl:

<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY nbsp "&#160;">

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

我的当前输出:

里面有一个非断行 <a href="http://localhost" target="_blank">空格</a>。

我期望的输出:

里面有一个 非断行 <a href="http://localhost" target="_blank">空格</a>。


能否展示一下你的“content” XML 的样例?谢谢! - Tim C
我在http://www.w3.org/TR/xslt20/#copy-of的`copy-of`元素上没有看到任何`disable-output-escaping`属性,因此我预计您的代码示例`<xsl:copy-of select="content" disable-output-escaping="yes"/>`只会被XSLT处理器报错。请考虑向我们展示更多有关输入样本、期望输出、当前输出以及您使用的XSLT处理器的详细信息。 - Martin Honnen
好的,我正在使用PHP中的XSLTProcessor类。实际上,“disable-output-escaping”属性没有出错,但是当我将其删除时,输出结果仍然相同。 - nourish
更新了我的问题,请给予您的想法。 - nourish
1个回答

0
基本上,输入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" 属性到链接的模板写得正确吗? - nourish
我认为模板并不重要,因为非断空格甚至不在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(而且@*将取决于当前实现在代码运行期间首先考虑哪个属性的值)。 - Martin Honnen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接