我有一个XSL模板,它匹配任何带有<var>
子元素的元素:
<xsl:template match="*[var]">
<xsl:copy >
<xsl:attribute name="editable">
<xsl:for-each select="var[@attr]">
<xsl:value-of
select="concat(@attr,
substring(' ',
1 div (position()!=last())))"/>
</xsl:for-each>
</xsl:attribute>
<xsl:attribute name="constraints">
<xsl:for-each select="var[@ok]">
<xsl:value-of
select="concat(@attr,':',@ok,
substring(';',
1 div (position()!=last())))"/>
</xsl:for-each>
</xsl:attribute>
<!-- if this is an <a> then we have to put the stuff inside it inside it -->
<xsl:apply-templates select="@*" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
它将var元素的attr
连接到父元素的editable
属性中;并ok
进入constraint
s。
然后我有一个匹配任何<field>
元素的模板:
<xsl:template match="field">
<span>
<xsl:attribute name="field">
<xsl:choose>
<xsl:when test="boolean(@name)">
<xsl:value-of select="./@name"/>
</xsl:when>
<xsl:otherwise>
<xsl:text>true</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:apply-templates />
</span>
</xsl:template>
这只是将其转换为<span field="name">
,其名称与字段相同,如果字段为1,则为“true”。
我遇到的问题是,*[var]
如果该字段的小时为<var>
,则匹配字段。但我想要发生的是*[var]
首先匹配 ,然后field
匹配以及,但之后< / em>的
目前,输入
<field name="field1">
<var attr="class" ok="small,smaller" />
Text
</field>
我得到了
<field name="field1" editable="class" constraints="class:small,smaller">
Text
</field>
但我想要
<span field="field1" editable="class" constraints="class:small,smaller">
Text
</span>
我找到了一些关于做两次通过的答案,但我不确定这是否是正确的答案,也不知道如何实现我找到的答案。我应该如何处理这个问题,如果有一个简单的答案,它是什么? :)
TIA Altreus
答案 0 :(得分:7)
如果要将两个模板应用于同一节点,可以使用xsl:next-match:从与节点匹配的最高优先级规则中,可以调用xs:next-match来调用次高,等等。当然,您可以使用xsl:template上的priority属性来“手动”调整优先级。
这里还有其他几种可能性:
(a)在我看来,“var”元素的处理可以在与var元素匹配的模板中完成而不是* [var],在这种情况下,它可以由xsl调用:以通常的方式应用模板
(b)第一个模板可以在特殊模式下使用apply-templates调用第二个模板
(c)第一个模板可以在变量中构造临时元素,然后将模板应用于该模板。
答案 1 :(得分:2)
此样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[var]">
<xsl:copy>
<xsl:call-template name="makeVarAttribute"/>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="field" priority="1">
<span field="{concat(@name,
substring('true',
1 div not(@name)
)
)}">
<xsl:apply-templates select="." mode="makeVarAttribute"/>
<xsl:apply-templates />
</span>
</xsl:template>
<xsl:template match="var"/>
<xsl:template match="node()" mode="makeVarAttribute"/>
<xsl:template match="*[var]"
name="makeVarAttribute"
mode="makeVarAttribute">
<xsl:attribute name="editable">
<xsl:for-each select="var[@attr]">
<xsl:value-of
select="concat(@attr,
substring(' ',
1 div (position()!=last())
)
)"/>
</xsl:for-each>
</xsl:attribute>
<xsl:attribute name="constraints">
<xsl:for-each select="var[@ok]">
<xsl:value-of
select="concat(@attr,':',@ok,
substring(';',
1 div (position()!=last())
)
)"/>
</xsl:for-each>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
输出:
<span field="field1" editable="class" constraints="class:small,smaller">
Text
</span>
注意:使用@priority
因为*[var]
模式的默认优先级高于field
,将公共内容模板封装在命名模板中,使用@mode
处理节点两次(首先是span
转换,然后属性,如果有var
子节点。)
修改:我没有看到xslt-2.0。这个XSLT 2.0样式表
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[var]">
<xsl:copy>
<xsl:call-template name="makeVarAttribute"/>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="field" priority="1">
<span field="{(@name,'true')[1]}">
<xsl:apply-templates select="." mode="makeVarAttribute"/>
<xsl:apply-templates />
</span>
</xsl:template>
<xsl:template match="var"/>
<xsl:template match="node()" mode="makeVarAttribute"/>
<xsl:template match="*[var]"
name="makeVarAttribute"
mode="makeVarAttribute">
<xsl:attribute name="editable" select="var/@attr"/>
<xsl:attribute name="constraints"
select="var[@ok]/concat(@attr,':',@ok)"
separator=";"/>
</xsl:template>
</xsl:stylesheet>
注意:序列处理,作为表达式的最后一步,@separator
。
答案 2 :(得分:0)
<xsl:template match="var">
<xsl:attribute name="editable">
<xsl:value-of select="@attr"/>
</xsl:attribute>
<xsl:attribute name="constraints">
<xsl:value-of select="concat(@attr,':',@ok)"/>
</xsl:attribute>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="field">
<span>
<xsl:attribute name="field">
<xsl:choose>
<xsl:when test="@name">
<xsl:value-of select="@name"/>
</xsl:when>
<xsl:otherwise>
<xsl:text>true</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:apply-templates />
</span>
</xsl:template>