我想在元素的属性中包含HTML(对于此处使用的数据清除属性:http://foundation.zurb.com/docs/components/clearing.html)。我的<caption>
数据有两种可用方式:
<caption mode="formatted">
<p>A fairly long looking <a href="http://www.stackoverflow.com">caption with a link</a> that goes to an external site.</p>
</caption>
<caption mode="unformatted">
<![CDATA[A fairly long looking <a href="http://www.stackoverflow.com">caption with a link</a> that goes to an external site.]]>
</caption>
这是我的模板:
<xsl:template match="images/entry">
<!-- process contents of caption node-->
<xsl:variable name="cap">
<xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text>
<xsl:apply-templates select="caption/*" mode="html" />
<xsl:text disable-output-escaping="yes">]]></xsl:text>
</xsl:variable>
<li>
<xsl:copy-of select="$cap"/> //outside of attribute it works
<img>
<xsl:attribute name="src">/image/2/150/112/5<xsl:value-of select="@path"/>/<xsl:value-of select="filename"/></xsl:attribute>
<xsl:attribute name="data-caption">
<xsl:copy-of select="$cap"/> //inside of attribute it removes the <a> tag
</xsl:attribute>
</img>
</li>
</xsl:template>
mode=html
将<caption>
节点中的<a>
标签与以下模板匹配:
<!-- mark external links -->
<xsl:template match="a" mode="html">
<a href="{@href}" title="{@title}">
<xsl:if test="number(substring(@href,1,4)='http')">
<xsl:attribute name="class">external</xsl:attribute>
<xsl:attribute name="target">_blank</xsl:attribute>
</xsl:if>
<xsl:apply-templates select="* | @* | text()" mode="html"/>
</a>
</xsl:template>
如果我使用"未格式化"的标题,它将保留<a>
标记(所需的行为)。但是,当我使用该标题时,我无法使用"标记外部链接"模板来修复<a>
标记。使用"格式化"的标题,我可以随心所欲地处理<a>
标记,但当我在<img>
<xsl:attribute>
中使用xsl:copy-of
时,它会丢失。它将在属性外显示精细,如下所示:
<![CDATA[<p>A fairly long looking <a href="http://www.stackoverflow.com" title="" class="external" target="_blank">caption with a link</a> that goes to an external site.</p>]]>
有没有办法让我的最终结果看起来像:
<img src="/image/2/150/112/5/images/my-image.jpg"
data-caption="<![CDATA[A fairly long looking <a class="external" target="_blank" href="http://www.stackoverflow.com">caption with a link</a> that goes to an external site.]]>;" />
感谢阅读。
首先,让我们明确您的属性中没有包含"节点";您想要的是序列化包含XML标记的属性。我们谈论的是词汇层面,而不是树层面,节点只存在于树层面。
要产生这种输出,有两个挑战。首先,您需要构造一个包含词法XML的字符串,然后将该字符串作为属性的值传递。其次,您需要防止这个字符串中的特殊字符被转义。
对于第一个问题,有两种方法:您可以调用一个外部serialize()函数,该函数将树转换为字符串形式的词法XML,例如saxon:serialize(如果您使用的是saxon:serialize),或者您可以编写自己的函数(这对于简单的情况来说并不困难,而且已经完成了-David Carlisle已经用XSLT编写了一个完整的XML序列化程序)。
第二个问题很棘手。XSLT序列化规范(所有版本)坚持HTML序列化方法不应转义出现在属性值中的"<",但它对">"几乎没有什么可说的。Saxon将">"转义为">"
,表面上是因为这是较旧的浏览器所需要的(现在可能已经很旧了!),但我认为规范不需要这一点,其他处理器可能会有所不同。禁用输出转义对属性值无效,因此您可能不得不使用禁用输出转义手动构建整个元素序列化。或者,使用XSLT2.0,您可以使用字符映射来强制输出属性值中的">"。
在示例代码中,在编写变量值时使用禁用输出转义。规范中有关于这一点的yoyo历史。XSLT1.0的一个勘误表(所谓的"粘性doe"勘误表)说这是允许的,但在XSLT2.0中却被推翻了,因为它与允许对变量中的结果树片段进行完全导航访问不兼容。因此,底线是,它可能工作,也可能不工作,这取决于您使用的处理器——当然,通常禁用输出转义也是如此。
对于这个需求,一个完全不同的解决方案可能是输出一些不同的东西——例如使用V形代替尖括号——然后通过文本过滤器过滤序列化的输出,该过滤器将相关字符替换为您实际想要的字符。