XSLT1.0实现三层级分组输出PDF的技术问题求解
问题原因
现有代码核心错误集中在分组规则和节点选择逻辑上:
- 三个层级的分组键全部匹配
Products节点,没有对应到Instruments和Bill层级的节点 - 分组键拼接未添加分隔符,可能出现不同命名拼接后重复的问题
- 内层循环全局遍历
/root/Products,没有限定在当前父分组范围内,导致取值和分组混乱
修正后的完整代码
<!-- 三级分组键定义,新增|作为分隔符避免命名冲突 --> <xsl:key name="groupProducts" match="/root/Products" use="@name"/> <xsl:key name="groupInstruments" match="Instruments" use="concat(parent::Products/@name, '|', @name)"/> <xsl:key name="groupBilling" match="Bill" use="concat(ancestor::Products/@name, '|', parent::Instruments/@name, '|', @name)"/> <xsl:template name="testing"> <fo:block> <fo:table> <fo:table-column column-width="proportional-column-width(1)"/> <fo:table-body> <!-- 第一级:按Products分组 --> <xsl:for-each select="/root/Products[generate-id(.) = generate-id(key('groupProducts',@name)[1])]"> <xsl:variable name="currentProductName" select="@name"/> <fo:table-row> <fo:table-cell> <fo:block font-weight="bold" margin-top="4pt"> <xsl:value-of select="@name"/> </fo:block> <fo:block margin-left="10pt"> <fo:table> <fo:table-column column-width="proportional-column-width(1)"/> <fo:table-body> <!-- 第二级:当前产品下按Instruments分组 --> <xsl:for-each select="key('groupProducts', $currentProductName)/Instruments[generate-id(.) = generate-id(key('groupInstruments', concat($currentProductName, '|', @name))[1])]"> <xsl:variable name="currentInstrumentName" select="@name"/> <fo:table-row> <fo:table-cell> <fo:block color="blue" margin-top="2pt"> Instruments: <xsl:value-of select="@name"/> </fo:block> <fo:block margin-left="10pt"> <fo:table> <fo:table-column column-width="proportional-column-width(1)"/> <fo:table-body> <!-- 第三级:当前仪器下按Bill分组 --> <xsl:for-each select="key('groupInstruments', concat($currentProductName, '|', $currentInstrumentName))/Bill[generate-id(.) = generate-id(key('groupBilling', concat($currentProductName, '|', $currentInstrumentName, '|', @name))[1])]"> <fo:table-row> <fo:table-cell> <fo:block color="green" margin-top="2pt"> Billing: <xsl:value-of select="@name"/> </fo:block> </fo:table-cell> </fo:table-row> </xsl:for-each> </fo:table-body> </fo:table> </fo:block> </fo:table-cell> </fo:table-row> </xsl:for-each> </fo:table-body> </fo:table> </fo:block> </fo:table-cell> </fo:table-row> </xsl:for-each> </fo:table-body> </fo:table> </fo:block> </xsl:template>
核心修改说明
- 重新定义三级分组键,分别匹配对应层级的节点,拼接时加入
|作为唯一分隔符,避免不同层级命名重复导致分组错误 - 内层循环限定在当前父分组的子节点范围内,不再全局遍历根节点,避免范围错误
- 新增变量存储上层分组标识,避免
current()嵌套时上下文混乱 - 节点取值使用相对路径,避免根路径匹配错误
内容的提问来源于stack exchange,提问作者iwasaki
相关产品推荐
相关产品推荐

