我对XSL、XPATH等都很陌生,有些代码是我的,有些是别人的。
问题:当下面的模板与我在下面描述的模板一起被调用时,if测试之后的所有xsl:text节点都被输出为一个字符串而不是一个xsl:text节点,因此图标不会被呈现。
这个问题与理解为什么有关?是怎么回事。我的确切问题是在这篇文章的末尾。
因此,我有一个模板,我调用它生成带有<use>元素的SVG元素,以便与sprite一起使用。
<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>所有类型的模板都调用/应用此模板。有一个特别的,我有一个问题。我们有两个由CMS实现的片段,它们输出相同的标记,但是代码段的配置实现方式不同,即页面模板A和页面模板B。模板的组织方式如下:
下面是上面演示的一些简化伪代码:
<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的结果。和/或稍后使用xsl:copy-of引用该变量。
我试过什么?
下面我有工作的和非工作的解决方案,所有这些我都不完全摸索为什么他们可以或不可能工作。
svg-link模板的文件向xsl:stylesheet添加xmlns:xlink="http://www.w3.org/1999/xlink",然后对svg-link模板进行修改,请参阅下面的代码列表。xsl:copy-of捕获xsl:call-template结果的xsl:variable的值。我将xsl:copy-of替换为与变量内部调用相同的第二个xsl:call-template。xsl:sequence而不是xsl:copy-of。xsl:variable属性捕获xsl:call-template的结果的as。即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>问题:为什么根据如何捕获/调用对xsl:call-template的调用结果,将svg-link模板的某些内容输出为字符串(而不是HTML)?正如你所看到的,我有工作和不工作的解决方案-我想知道为什么。谢谢!
发布于 2019-05-03 20:34:06
首先,disable-output-escaping是一个可选的序列化特性。此外,XSLT 2或3规范在根本不起作用时会详细说明,请参见https://www.w3.org/TR/xslt-30/#disable-output-escaping
如果在临时输出状态生效时对
xsl:value-of或xsl:text指令禁用输出转义,则将忽略禁用输出转义的请求。
和https://www.w3.org/TR/xslt-30/#dt-temporary-output-state
xsl:变量、xsl:param、xsl:with、xsl:function、xsl:key、xsl:sort、xsl:累加器-规则和xsl:merge-key总是在临时输出状态下计算包含的序列构造函数中的指令。
因此,在您的xsl:variable中,任何disable-output-escaping都不能工作。
使用它来构造SVG use元素的整个尝试是完全不必要的,您可以将任何结果元素创建为文字结果元素,例如<use xlink:href="{concat( '#', $svg-loc )}"></use> (该名称空间的属性范围内有适当的XLink名称空间声明),或者,如果需要计算部分名称或名称空间,则使用xsl:element。
https://stackoverflow.com/questions/55972533
复制相似问题