XSLT编号需求:为相邻or-item实现对应位置的二级编号
解决同级
<or-item>的二级编号问题 我明白你的痛点——没法调整XML结构,只能从同级元素里把<or-item>和对应的<item>关联起来生成正确的二级编号。原来的代码里统计所有<or-item>总数的方式肯定不对,咱们来修改一下:
XSLT 1.1 兼容版本(适配xsltproc)
这个版本用XPath计算当前<or-item>在对应<item>组内的位置,完全兼容你当前的运行环境:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" version="1.1" xmlns:axf="http://www.antennahouse.com/names/XSL/Extensions" xmlns:fn="http://www.w3.org/2005/xpath-functions"> <xsl:output encoding="UTF-8" method="html" indent="yes"/> <xsl:template match="list"> <div> <xsl:apply-templates/> </div> </xsl:template> <xsl:template match="item"> <div> <xsl:number count="item"/> <xsl:text> </xsl:text> <xsl:value-of select="."/> </div> </xsl:template> <xsl:template match="or-item"> <div style="padding-left: 10px"> <!-- 核心逻辑:找到和当前or-item同属一个前置item的所有同级or-item,计算当前位置 --> <xsl:number value="count(preceding-sibling::or-item[preceding-sibling::item[1] = current()/preceding-sibling::item[1]]) + 1" format="a) "/> <xsl:value-of select="."/> </div> </xsl:template> </xsl:stylesheet>
逻辑拆解
这段XPath的作用是:
current()/preceding-sibling::item[1]→ 获取当前<or-item>前面最近的那个<item>preceding-sibling::or-item[preceding-sibling::item[1] = ...]→ 筛选出所有和当前<or-item>共享同一个最近<item>的前置<or-item>- 统计这些元素的数量再加1,就是当前
<or-item>在组内的序号,配合format="a) "生成a)、b)这样的二级编号格式。
XSLT 2.0 简化版本(如果支持的话)
如果你的环境可以兼容XSLT 2.0,用分组功能会更清晰,代码可读性更强:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" version="2.0" xmlns:axf="http://www.antennahouse.com/names/XSL/Extensions" xmlns:fn="http://www.w3.org/2005/xpath-functions"> <xsl:output encoding="UTF-8" method="html" indent="yes"/> <xsl:template match="list"> <div> <!-- 按item分组,把item和后面连续的or-item归为一组 --> <xsl:for-each-group select="item | or-item" group-starting-with="item"> <!-- 处理组内的第一个元素(就是item) --> <div> <xsl:number count="item"/> <xsl:text> </xsl:text> <xsl:value-of select="current-group()[1]"/> </div> <!-- 处理组内剩下的or-item --> <xsl:apply-templates select="current-group()[position() > 1]"/> </xsl:for-each-group> </div> </xsl:template> <xsl:template match="or-item"> <div style="padding-left: 10px"> <!-- 直接用组内的position()作为二级编号 --> <xsl:number value="position()" format="a) "/> <xsl:value-of select="."/> </div> </xsl:template> </xsl:stylesheet>
逻辑拆解
用group-starting-with="item"把<list>下的元素按“item开头,后面跟连续的or-item”分组,每组对应一个item和它的备选项。处理组内元素时,item用一级编号,后面的or-item直接用组内的位置生成二级编号,逻辑更直观。
测试你的XML输入,最终输出的HTML会是:
<div> <div>1 Test</div> <div style="padding-left: 10px">a) TestOr</div> <div style="padding-left: 10px">b) TestOrr</div> <div>2 Testtt</div> <div style="padding-left: 10px">a) TestOrrr</div> <div>3 Testttt</div> </div>
内容的提问来源于stack exchange,提问作者Pascal
相关产品推荐
相关产品推荐

