如何在XSLT中按出现位置分组包裹无属性节点
解决XSLT中按连续位置分组
<Aufzhlungbullets>元素的问题 嘿,我看你在XSLT分组上遇到了点小麻烦——想把连续出现的<Aufzhlungbullets>用<list>分别包裹,但现在的代码把所有这类元素都揉成一个大组了对吧?这问题其实换个分组方式就能解决,咱们一步步来。
原文档
<modul> <body> <Standard>some text</Standard> <Herausforderung>some text</Herausforderung> <Standard>some text <d2tb>some text</d2tb> </Standard> <Aufzhlungbullets>some text</Aufzhlungbullets> <Aufzhlungbullets>some text</Aufzhlungbullets> <Aufzhlungbullets>some text</Aufzhlungbullets> <Standard>some text <d2ti>some text</d2ti> </Standard> <Aufzhlungbullets>some text</Aufzhlungbullets> <Aufzhlungbullets>some text</Aufzhlungbullets> <Aufzhlungbullets>some text</Aufzhlungbullets> <Standard>some text</Standard> </body> </modul>
期望输出
<modul> <body> <Standard>some text</Standard> <Herausforderung>some text</Herausforderung> <Standard>some text <d2tb>some text</d2tb> </Standard> <list> <Aufzhlungbullets>some text</Aufzhlungbullets> <Aufzhlungbullets>some text</Aufzhlungbullets> <Aufzhlungbullets>some text</Aufzhlungbullets> </list> <Standard>some text <d2ti>some text</d2ti> </Standard> <list> <Aufzhlungbullets>some text</Aufzhlungbullets> <Aufzhlungbullets>some text</Aufzhlungbullets> <Aufzhlungbullets>some text</Aufzhlungbullets> </list> <Standard>some text</Standard> </body> </modul>
当前XSLT样式表(存在问题)
<xsl:template match="body"> <list> <xsl:for-each-group select="Aufzhlungbullets" group-by="."> <xsl:copy-of select="current-group()"/> </xsl:for-each-group> </list> </xsl:template>
你的问题出在group-by="."上——这个是按元素的内容来分组,不管位置,所以所有内容相同的<Aufzhlungbullets>都会被归到一个大组里。要实现按连续出现的位置分组,咱们得用group-adjacent这个分组方式。
解决方案:使用group-adjacent按相邻元素分组
调整后的XSLT代码
<xsl:template match="body"> <xsl:copy> <!-- 遍历body下的所有子节点,按是否为Aufzhlungbullets分组 --> <xsl:for-each-group select="*" group-adjacent="local-name() = 'Aufzhlungbullets'"> <!-- 如果是连续的Aufzhlungbullets组,用list包裹 --> <xsl:if test="current-grouping-key()"> <list> <xsl:copy-of select="current-group()"/> </list> </xsl:if> <!-- 如果是非Aufzhlungbullets的元素,直接复制保留 --> <xsl:if test="not(current-grouping-key())"> <xsl:copy-of select="current-group()"/> </xsl:if> </xsl:for-each-group> </xsl:copy> </xsl:template> <!-- 保留默认的复制模板,确保文档其他节点结构不变 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template>
代码说明
group-adjacent的作用:group-adjacent="local-name() = 'Aufzhlungbullets'"会把连续的<Aufzhlungbullets>元素归为一组,把其他连续的非目标元素(比如<Standard>、<Herausforderung>)归为单独的组,完美匹配你按位置分组的需求。- 分组后的处理:
- 当
current-grouping-key()为true时,说明当前组是连续的<Aufzhlungbullets>,我们用<list>标签包裹这一组元素。 - 当
current-grouping-key()为false时,直接复制这一组非目标元素,保留原有的结构和内容。
- 当
- 默认模板的作用:最后那个默认模板是为了确保文档中其他节点(比如
<modul>、<Standard>里的子元素)都能被正确复制,不会因为只处理<body>而丢失部分内容。
运行这段代码后,就能得到你想要的输出:每一段连续的<Aufzhlungbullets>都会被单独的<list>包裹,其他元素完全保持原样。
内容的提问来源于stack exchange,提问作者Pjoern
相关产品推荐
相关产品推荐

