如何在@id与ref元素值不匹配时生成连续num属性序列?
如何为匹配ref元素的obj生成连续的num属性值?
需要为XML中符合条件的<obj>元素生成连续数字的num属性——仅当<obj>的@id与<root>下的<ref>元素值匹配时,才生成对应的<p>元素,且其num属性要按1、2、3...连续排列。当前实现得到的num是原obj的位置(1、3、5),需要调整为连续序列。
输入XML
<root> <p><obj id="a1"/><obj id="a2"/><obj id="a3"/><obj id="a4"/><obj id="a5"/></p> <ref>a1</ref> <ref>a20</ref> <ref>a3</ref> <ref>a40</ref> <ref>a5</ref> </root>
尝试的XSLT
<xsl:template match="root/p"> <root> <xsl:for-each select="obj"> <xsl:variable name="id" select="@id"/> <xsl:if test="ancestor::root//ref = $id"> <xsl:variable name="position"><xsl:number level="any" count="obj"/></xsl:variable> <p num="{$position}" value="{$id}"/> </xsl:if> </xsl:for-each> </root> </xsl:template> <xsl:template match="ref"/>
现有输出
<root> <p num="1" value="a1"/> <p num="3" value="a3"/> <p num="5" value="a5"/> </root>
期望输出
<root> <p num="1" value="a1"/> <p num="2" value="a3"/> <p num="3" value="a5"/> </root>
解决方案
问题出在原代码中<xsl:number count="obj"/>会统计所有<obj>的位置,而非仅符合匹配条件的<obj>。可以通过两种方式修正:
方式一:先筛选再循环
直接在<xsl:for-each>的select中过滤出匹配的<obj>,然后用position()获取当前循环的序号:
<xsl:template match="root/p"> <root> <xsl:for-each select="obj[ancestor::root//ref = @id]"> <p num="{position()}" value="{@id}"/> </xsl:for-each> </root> </xsl:template> <xsl:template match="ref"/>
方式二:调整<xsl:number>的统计条件
如果需要保留原循环结构,修改<xsl:number>的count属性,仅统计符合条件的<obj>:
<xsl:template match="root/p"> <root> <xsl:for-each select="obj"> <xsl:variable name="id" select="@id"/> <xsl:if test="ancestor::root//ref = $id"> <p num="{xsl:number level='any' count='obj[ancestor::root//ref = @id]'}" value="{$id}"/> </xsl:if> </xsl:for-each> </root> </xsl:template> <xsl:template match="ref"/>
两种方式都能得到期望的连续num序列,其中方式一更简洁高效,因为它只循环符合条件的元素。
内容的提问来源于stack exchange,提问作者Yug
相关产品推荐
相关产品推荐

