使用XSLT合并多个独立ol类型inlineTag为单个有序列表
解决方案
核心思路是使用XSLT的相邻分组能力,将连续的同类型列表节点合并为单个列表容器:
前置注意事项
你提供的XML带有默认命名空间http://www.vjoon.com/K4Export/2.6,需要在XSLT中先声明该命名空间才能正确匹配节点。
完整XSLT示例(基于XSLT 2.0+,主流解析器均支持)
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:k4="http://www.vjoon.com/K4Export/2.6" exclude-result-prefixes="k4"> <!-- 处理Textabschnitt层的子节点,按相邻同name属性分组 --> <xsl:template match="k4:inlineTag[@name='Textabschnitt']"> <xsl:for-each-group select="k4:inlineTag" group-adjacent="@name"> <xsl:choose> <!-- 合并有序列表 --> <xsl:when test="current-grouping-key()='ol'"> <ol class="imported"> <xsl:for-each select="current-group()"> <li> <xsl:value-of select="normalize-space(.)"/> </li> </xsl:for-each> </ol> </xsl:when> <!-- 合并无序列表 --> <xsl:when test="current-grouping-key()='ul'"> <ul class="imported"> <xsl:for-each select="current-group()"> <li> <xsl:value-of select="normalize-space(.)"/> </li> </xsl:for-each> </ul> </xsl:when> <!-- 其他类型节点走原有处理逻辑 --> <xsl:otherwise> <xsl:apply-templates select="current-group()"/> </xsl:otherwise> </xsl:choose> </xsl:for-each-group> </xsl:template> <!-- 原有其他inlineTag处理规则 --> <xsl:template match="k4:inlineTag[@name='h3']"> <h3><xsl:value-of select="normalize-space(.)"/></h3> </xsl:template> <xsl:template match="k4:inlineTag[@name='p']"> <p><xsl:value-of select="normalize-space(.)"/></p> </xsl:template> <xsl:template match="k4:inlineTag[@name='blockquote']"> <blockquote><xsl:value-of select="normalize-space(.)"/></blockquote> </xsl:template> <xsl:template match="k4:inlineTag[@name='h4']"> <h4><xsl:value-of select="normalize-space(.)"/></h4> </xsl:template> </xsl:stylesheet>
效果说明
连续的name=ol或name=ul节点会被自动归为同一组,生成单个外层列表标签包裹所有li项,中间被其他类型节点(如p、h3)隔开的列表会自动拆分为多个独立列表,符合常规排版需求。
XSLT 1.0兼容方案
如果只能使用XSLT 1.0,可通过相邻节点判断实现分组:匹配到name=ol的节点时,先判断前一个相邻节点是否也是name=ol,如果不是则输出<ol>开始标签,然后输出当前li,再判断后一个相邻节点是否是name=ol,如果不是则输出</ol>结束标签即可。
内容的提问来源于stack exchange,提问作者Noel Bügler
相关产品推荐
相关产品推荐

