1

我想在元素的属性中包含 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">&lt;![CDATA[</xsl:text>
        <xsl:apply-templates select="caption/*" mode="html" />
        <xsl:text disable-output-escaping="yes">]]&gt;</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匹配:<a><caption>

<!-- 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>像我想要的那样处理标签,但是当我xsl:copy-of<img> <xsl:attribute>. 它将在属性之外正常显示,如下所示:

<![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.]]>;" />

谢谢阅读。

4

1 回答 1

3

首先,让我们明确一点,您的属性中不包括“节点”;您想要的是序列化包含 XML 标记的属性。我们在词汇级别而不是树级别进行讨论,节点仅存在于树级别。

要生成此输出,有两个挑战。首先,您需要构造一个包含词法 XML 的字符串,然后将该字符串作为属性的值传递。其次,您需要防止此字符串中的特殊字符被转义。

对于第一个问题,有两种方法:您可以调用外部 serialize() 函数将树转换为作为字符串的词法 XML,例如 saxon:serialize() 如果您使用的是 Saxon,或者您可以编写自己的 (这对于简单的情况并不难,而且已经完成了——David Carlisle 用 XSLT 编写了一个完整的 XML 序列化程序)。

第二个问题很棘手。XSLT 序列化规范(所有版本)坚持认为 HTML 序列化方法不应转义出现在属性值中的“<”,但它对“>”几乎没有或根本没有说。Saxon 将 ">" 转义为"&gt;",表面上是因为旧版浏览器需要这样做(现在可能已经很老了!),但我认为规范不需要这样做,其他处理器可能会有所不同。禁用输出转义不适用于属性值,因此您可能不得不求助于使用禁用输出转义手动构建整个元素序列化。或者,使用 XSLT 2.0,您可以使用字符映射来强制在属性值中输出“>”。

在您的示例代码中,您在写入变量的值时使用了禁用输出转义。在规范中有一个悠悠球的历史。XSLT 1.0 的一个勘误表(所谓的“sticky doe”勘误表)说它是允许的,但在 XSLT 2.0 中这被颠倒了,因为它与允许对变量中保存的结果树片段的完全导航访问不兼容。所以最重要的是,它可能会或可能不会工作,具体取决于您使用的处理器 - 但当然,通常禁用输出转义也是如此。

对此要求的完全不同的解决方案可能是输出不同的内容 - 例如使用 V 形代替尖括号 - 然后通过文本过滤器过滤序列化输出,将相关字符替换为您实际想要的字符。

于 2013-09-05T08:10:55.687 回答