问题:SVG <use> 元素在 XSL 模板中转换为字符串

Issue: SVG <use> Element is Converted to String in XSL Template

我对 XSL、XPATH 等还很陌生。有些代码是我的,有些是别人的。

问题: 当使用我在下面进一步概述的模板调用下面的模板时,if 测试后的所有 xsl:text 节点都作为字符串输出而不是 HTML 节点,因此不会呈现图标。

这个问题与了解正在发生的事情的为什么?有关。我的确切问题在这个 post.

的底部

所以,我有一个我调用的模板,它生成带有 <use> 元素的 SVG 元素,用于 SVG 精灵。

<xsl:template name="svg-link">

  <xsl:param name="svg-id"/>
  <xsl:param name="svg-class"/>
  <xsl:param name="svg-title"/>

  <span class="{$svg-class} svgstore svgstore--{$svg-loc}">
    <svg>
      <xsl:if test="$svg-title != ''">
        <title><xsl:value-of select="$svg-title"/></title>
      </xsl:if>
      <xsl:text disable-output-escaping="yes">&lt;use xlink:href="</xsl:text>
      <xsl:value-of select="concat('#', $svg-loc)" />
      <xsl:text disable-output-escaping="yes">"&gt;&lt;/use&gt;</xsl:text>
    </svg>
  </span>

</xsl:template>

各种模板call/apply这个模板。有一个特别是我有问题。我们有两个由 CMS 实现的片段,它们输出相同的标记,但片段的配置实现不同,即页面模板 A 与页面模板 B。所讨论的片段由多个 XSL 模板组成。模板的组织方式如下:

下面是上面演示的一些简化的伪代码:

<xsl:template name="snippet">

  <xsl:param name="outer-classes"/>
  <xsl:param name="inner-classes"/>

  <xsl:variable name="items">
    <xsl:call-template name="snippet-model"/>
  </xsl:variable>

  <!-- Render Snippet if it has content. -->
  <xsl:if test="count( $items )">
    <div class="{ $outer-classes }">
      <div class="{ $inner-classes }">
        <xsl:copy-of select="$items">
      </div>
    </div>
  </xsl:if>

</xsl:template>

<!-- Placeholder. Defined by each page template. -->
<xsl:template name="snippet-model"/>

<xsl:template name="snippet-item">

  <xsl:param name="a"/>
  <xsl:param name="b"/>
  <xsl:param name="b"/>

  <div class="snippet-item {$a}">

    <xsl:apply-templates select="$b"/>

    <xsl:call-template name="svg-link">
      <xsl:with-param name="svg-id">alpha</xsl:with-param>
      <xsl:with-param name="svg-class">alpha</xsl:with-param>
      <xsl:with-param name="svg-title">The Title</xsl:with-param>
    </xsl:call-template>
  </div>

</xsl:template>

以及页面模板如何使用上述内容的示例:

<xsl:template match="table[@class = 'snippet-alpha']">

  <xsl:call-template="snippet">
    <xsl:with-param name="outer-classes">page-template-a other</xsl:with-param>
    <xsl:with-param name="inner-classes">some-template-modifier</xsl:with-param>
  </xsl:call-template>

</xsl:template>

<!-- Template definition of `snippet-model` template. -->
<xsl:template name="snippet-model">

  <!-- Another page template might not use `tbody/tr` to loop over. -->
  <xsl:for-each select="tbody/tr">
    <xsl:call-template="snippet-item">
      <xsl:with-param name="a" select="td[1]"/>
      <xsl:with-param name="b" select="td[2]"/>
      <xsl:with-param name="c" select="td[3]"/>
    </xsl:call-template>
  </xsl:for-each>

</xsl:template>

我已将我的问题缩小到可能是 xsl:variablesnippet 模板中捕获 xsl:call-template 的结果。 And/Or 稍后用 xsl:copy-of.

引用该变量

我尝试了什么?

下面我有有效无效解决方案,所有这些我都没有完全理解为什么它们可能有效或无效.

  • 有效: 为包含 svg-link 模板的文件添加 xmlns:xlink="http://www.w3.org/1999/xlink"xsl:stylesheet,然后修改 svg-link 模板,请参阅此列表下方的代码。
  • Works: 而不是输出 xsl:variable 的值,用 xsl:copy-of 捕获 xsl:call-template 的结果。我将 xsl:copy-of 替换为第二个 xsl:call-template,这与在变量内部完成的调用相同。
  • 不起作用: 使用 xsl:sequence 而不是 xsl:copy-of
  • 不工作: 尝试数据输入(?) xsl:variable 捕获具有 as 属性的 xsl:call-template 结果。 IE。 as="node()*".
<xsl:template name="svg-link">

  <xsl:param name="svg-id"/>
  <xsl:param name="svg-class"/>
  <xsl:param name="svg-title"/>

  <span class="{$svg-class} svgstore svgstore--{$svg-loc}">
    <svg>
      <xsl:if test="$svg-title != ''">
        <title><xsl:value-of select="$svg-title"/></title>
      </xsl:if>
      <use xlink:href="{concat( '#', $svg-loc )}"></use>
    </svg>
  </span>

</xsl:template>

问题:为什么svg-link模板的一些内容根据结果如何输出为字符串(而不是HTML)对 xsl:call-template 的调用是 captured/called?如您所见,我有有效和无效的解决方案 - 我想知道为什么。谢谢!

首先,disable-output-escaping是一个可选的序列化功能。此外,当 XSLT 2 或 3 规范根本不起作用时,请参阅 https://www.w3.org/TR/xslt-30/#disable-output-escaping

If output escaping is disabled for an xsl:value-of or xsl:text instruction evaluated when temporary output state is in effect, the request to disable output escaping is ignored.

https://www.w3.org/TR/xslt-30/#dt-temporary-output-state

xsl:variable, xsl:param, xsl:with-param, xsl:function, xsl:key, xsl:sort, xsl:accumulator-rule, and xsl:merge-key always evaluate the instructions in their contained sequence constructor in temporary output state

所以在你的 xsl:variable 里面任何 disable-output-escaping 都不能工作。

使用它来构建 SVG use 元素的整个尝试是完全没有必要的,您可以创建任何结果元素作为文字结果元素,例如<use xlink:href="{concat( '#', $svg-loc )}"></use>(在该命名空间的属性范围内使用适当的 XLink 命名空间声明),或者,如果您需要计算部分名称或命名空间,请使用 xsl:element.