问题: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"><use xlink:href="</xsl:text>
<xsl:value-of select="concat('#', $svg-loc)" />
<xsl:text disable-output-escaping="yes">"></use></xsl:text>
</svg>
</span>
</xsl:template>
各种模板call/apply这个模板。有一个特别是我有问题。我们有两个由 CMS 实现的片段,它们输出相同的标记,但片段的配置实现不同,即页面模板 A 与页面模板 B。所讨论的片段由多个 XSL 模板组成。模板的组织方式如下:
- 代码段模板: 所有调用者的代码段入口点。接受一些与 CSS 类 相关的参数。为片段创建一些包装器元素。调用以下模板。
- "Model"模板:是一个模板,需要每个页面模板定义。如上所述,每个页面模板都使用不同的方法来实现代码段的配置选项。这个想法是让下面的模板首先不知道代码段是如何配置的,因为这个模板负责了解这些细节并将其传递给下面的模板。
- 片段项目模板: 根据 "Model" 模板 [=83] 传递给它的信息呈现片段的大部分标记=].
下面是上面演示的一些简化的伪代码:
<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:variable
在 snippet
模板中捕获 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
.
我对 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"><use xlink:href="</xsl:text>
<xsl:value-of select="concat('#', $svg-loc)" />
<xsl:text disable-output-escaping="yes">"></use></xsl:text>
</svg>
</span>
</xsl:template>
各种模板call/apply这个模板。有一个特别是我有问题。我们有两个由 CMS 实现的片段,它们输出相同的标记,但片段的配置实现不同,即页面模板 A 与页面模板 B。所讨论的片段由多个 XSL 模板组成。模板的组织方式如下:
- 代码段模板: 所有调用者的代码段入口点。接受一些与 CSS 类 相关的参数。为片段创建一些包装器元素。调用以下模板。
- "Model"模板:是一个模板,需要每个页面模板定义。如上所述,每个页面模板都使用不同的方法来实现代码段的配置选项。这个想法是让下面的模板首先不知道代码段是如何配置的,因为这个模板负责了解这些细节并将其传递给下面的模板。
- 片段项目模板: 根据 "Model" 模板 [=83] 传递给它的信息呈现片段的大部分标记=].
下面是上面演示的一些简化的伪代码:
<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:variable
在 snippet
模板中捕获 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
orxsl: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
.