在这个xml中:
<root>
<a/>
<b/>
<c/>
<x/>
<b/>
<c/>
<a/>
</root>
我希望在a之后的任何组合中添加任何a和任何b或c的属性,直到达到某个其他元素,如下所示:
<root>
<a myattr='yes'/>
<b myattr='yes'/>
<c myattr='yes'/>
<x/>
<b/>
<c/>
<a myattr='yes'/>
</root>
请注意,忽略前面a的b或c。 我想要的是处理a,然后在它的模板中执行for-each -sibling :: b或c并处理它们,但是我如何“抛出”处理超出这些元素以便处理开始(在这个例子)在x?
这可能吗?
答案 0 :(得分:1)
以下XSLT样式表应生成所需的输出。
在匹配b
和c
元素时,会查找前一个a
和“a
,b
以及{{1}以外的任何内容“兄弟姐妹并比较他们的立场。如果c
兄弟是最近的,那么它会添加属性。
a
答案 1 :(得分:0)
你可以通过“一次一个兄弟”尾递归来做到这一点。从你之前的问题我收集到你正在使用XSLT 2.0,所以你可以使用下一个匹配非常优雅地做到这一点
<xsl:template match="root">
<xsl:copy><xsl:apply-templates select="*[1]" /></xsl:copy>
</xsl:template>
<xsl:template match="a">
<xsl:param name="inGroup"/>
<xsl:next-match>
<!-- a is always in a group -->
<xsl:with-param name="inGroup" select="true()" />
</xsl:next-match>
</xsl:template>
<xsl:template match="*[not(self::a | self::b | self::c)]">
<xsl:param name="inGroup"/>
<xsl:next-match>
<!-- anything other than a, b, c is never in a group -->
<xsl:with-param name="inGroup" select="false()" />
</xsl:next-match>
</xsl:template>
<!-- b and c will match this directly, and take their "groupiness" from the
previous iteration -->
<xsl:template match="*">
<xsl:param name="inGroup"/>
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:if test="$inGroup">
<xsl:attribute name="myattr">yes</xsl:attribute>
</xsl:if>
<xsl:copy-of select="node()" />
</xsl:copy>
<!-- process the next sibling, passing on the group flag -->
<xsl:apply-templates select="following-sibling::*[1]">
<xsl:with-param name="inGroup" select="$inGroup" />
</xsl:apply-templates>
</xsl:template>
相同的代码应该在1.0中有效,除非您需要为*
模板name
以及match
提供,然后使用call-template
代替{{ 1}}。
答案 2 :(得分:-1)
我想在XSLT 1.0中尝试这个:
...
<xsl:template match="a">
<xsl:copy>
<xsl:attribute name="myattr">yes</xsl:attribute>
</xsl:copy>
</xsl:template>
<xsl:template match="b|c">
<xsl:copy>
<xsl:variable name="lineage">
<xsl:call-template name="lineage"/>
</xsl:variable>
<xsl:if test="$lineage = 'true'">
<xsl:attribute name="myattr">yes</xsl:attribute>
</xsl:if>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:copy/>
</xsl:template>
<xsl:template name="lineage">
<xsl:param name="i" select="1"/>
<xsl:choose>
<xsl:when test="$i > count(preceding-sibling::*)"/>
<xsl:when test="name(preceding-sibling::*[$i])='a'">
<xsl:value-of select="true()"/>
</xsl:when>
<xsl:when test="name(preceding-sibling::*[$i])='b'
or
name(preceding-sibling::*[$i])='c'">
<xsl:call-template name="lineage">
<xsl:with-param name="i" select="$i+1"/>
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:template>