如何在 <xsl:attribute> 文本中生成标记?

How to generate markup inside of <xsl:attribute> text?

我的 XSLT 样式表生成 Bootstrap HTML where some elements may contain data-... attributes to pass additional data to the framework. For example, I have this code to generate a popover 元素:

<xsl:template match="foo">
  <a href="#" data-toggle="popover" data-placement="top" data-trigger="hover" data-html="true">
    <xsl:attribute name="title">Popover Title</xsl:attribute>
    <xsl:attribute name="data-content">This is some additional content.</xsl:attribute>
    <xsl:text>Link</xsl:text>
  </a>
</xsl:template>

data-content 属性应该包含附加标记。结果输出应该类似于

<a href="#" ... data-content="This is <em>some</em> additional <a href='#'>content</a>.">Link</a>

在这种情况下,如何为 <xsl:attribute> 生成标记文本?

(有些相关:here and here and here。)

答案

感谢您的回答!虽然我认为 provides the technically correct solution to implement properly what I need, I think that 更直接地解决了我的问题。

您不能在 xsl:attribute 内生成标记,因为 XML 不允许在属性内使用未转义的标记。

具体来说,AttValuegrammar rule 完全禁止 <&,除非 & 是格式正确的 Reference 的一部分:

AttValue       ::=      '"' ([^<&"] | Reference)* '"'
                      | "'" ([^<&'] | Reference)* "'"

支持定义:

Reference      ::=      EntityRef | CharRef
EntityRef      ::=      '&' Name ';'
CharRef        ::=      '&#' [0-9]+ ';'
                      | '&#x' [0-9a-fA-F]+ ';'

HTML 也一样,甚至 HTML5,也不允许在属性值中使用未转义的标记。

在属性值中添加转义标记是可行的,但很难看。特别是对于大量标记的内容,我建议单独创建内容,然后通过 JavaScript 以程序方式关联它,而不是通过属性值以声明方式关联。这样做的例子有很多,包括您的一篇参考文献中提到的 this one

您不能将未转义的标记放在属性值中,但是 you don't need to - 如果您将尖括号(以及任何与号和引号内的引号)转义为实体引用 bootstrap 将仍然在弹出窗口中正确呈现 html。

<a href="#" data-content="This is &lt;em&gt;some&lt;/em&gt; additional &lt;a href='#'&gt;content&lt;/a&gt;.">Link</a>

在 XSLT 中做到这一点的最简单方法是使用 CDATA 部分:

<xsl:attribute name="data-content"
  ><![CDATA[This is <em>some</em> additional content
    &amp; a <a href="#">link</a>.]]></xsl:attribute>

序列化程序会根据需要为您转义它。

不是 "official" 的方式,而是在您的样式表中使用 lxml to process the XML and XSLT stylesheets, consider using XSLT extension elements 时。这些自定义元素允许您在处理过程中元素匹配时 运行 Python 编码,并且该代码可以 modify/edit 部分输出文档。