如何使用XSLT 1.0根据子元素值拆分XML image元素分组
解决XSLT 1.0中按size分组
元素的问题
需求
需要将元素按子元素
- size为
full的单独放入一个
- size为
half的:
- 相邻的两个
half成对放入同一个 - 单个
half单独放入
- 相邻的两个
现有代码的缺陷
你之前的代码通过for-each选择image[not(preceding-sibling::image[1][size='half'] and size='half')]作为组的起始节点,但这种方式会漏掉连续奇数个half中的最后一个——比如三个连续half时,第三个half的前一个是half,因此不会被选中,最终丢失。
正确的XSLT 1.0实现
使用递归模板处理节点,确保每个节点都被覆盖,同时跳过已处理的节点:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <!-- 根模板,启动分组处理 --> <xsl:template match="imagecollection"> <imagecollection> <!-- 从第一个image开始递归处理 --> <xsl:apply-templates select="imageset/image[1]" mode="group"/> </imagecollection> </xsl:template> <!-- 分组处理模板 --> <xsl:template match="image" mode="group"> <imageset> <!-- 复制当前节点 --> <xsl:copy-of select="."/> <!-- 如果当前是half且下一个也是half,复制下一个节点 --> <xsl:if test="size='half' and following-sibling::image[1][size='half']"> <xsl:copy-of select="following-sibling::image[1]"/> </xsl:if> </imageset> <!-- 计算下一个要处理的节点位置:如果当前是成对的half,跳2个;否则跳1个 --> <xsl:variable name="step" select="if (size='half' and following-sibling::image[1][size='half']) then 2 else 1"/> <!-- 递归处理下一个节点 --> <xsl:apply-templates select="following-sibling::image[$step]" mode="group"/> </xsl:template> </xsl:stylesheet>
测试验证
测试案例1:混合full和half的源数据
处理后会生成正确的分组,每个full单独一组,成对half一组,单个half一组。
测试案例2:三个连续half的源数据
转换后输出:
<imagecollection> <imageset> <image> <size>half</size> <id>a group 1</id> </image> <image> <size>half</size> <id>b group 1</id> </image> </imageset> <imageset> <image> <size>half</size> <id>c group 2</id> </image> </imageset> </imagecollection>
第三个half不再丢失,完全符合需求。
内容的提问来源于stack exchange,提问作者deuri
相关产品推荐
相关产品推荐

