XSLT分组需求:按type和pin字段合并或拆分file节点
问题描述
需求规则:
- 当
<file>节点的type和pin字段值均存在且相同时,将这些<file>合并到同一个<cat>节点下 - 若
type存在但pin值为空,则每个<file>节点单独生成一个<cat>节点
给定输入XML如下:
<?xml version='1.0' encoding='UTF-8'?> <record> <file> <type>DI</type> <pin>123</pin> </file> <file> <type>DI</type> <pin>123</pin> </file> <file> <type>DI</type> <pin>456</pin> </file> <file> <type>DI</type> <pin></pin> </file> <file> <type>DI</type> <pin></pin> </file> <file> <type>DM</type> <pin>123</pin> </file> <file> <type>DM</type> <pin>123</pin> </file> <file> <type>DM</type> <pin>456</pin> </file> <file> <type>DM</type> <pin></pin> </file> <file> <type>DM</type> <pin></pin> </file> <file> <type>CM</type> <pin>123</pin> </file> <file> <type>CM</type> <pin>123</pin> </file> <file> <type>CM</type> <pin>456</pin> </file> <file> <type>CM</type> <pin></pin> </file> <file> <type>CM</type> <pin></pin> </file> </record>
预期输出XML:
<?xml version='1.0' encoding='UTF-8'?> <root> <record> <cat> <file> <type>DI</type> <pin>123</pin> </file> <file> <type>DI</type> <pin>123</pin> </file> </cat> <cat> <file> <type>DM</type> <pin>123</pin> </file> <file> <type>DM</type> <pin>123</pin> </file> </cat> <cat> <file> <type>CM</type> <pin>123</pin> </file> <file> <type>CM</type> <pin>123</pin> </file> </cat> <cat> <file> <type>DI</type> <pin>456</pin> </file> </cat> <cat> <file> <type>DM</type> <pin>456</pin> </file> </cat> <cat> <file> <type>CM</type> <pin>456</pin> </file> </cat> <cat> <file> <type>DI</type> <pin></pin> </file> </cat> <cat> <file> <type>DI</type> <pin></pin> </file> </cat> <cat> <file> <type>DM</type> <pin></pin> </file> </cat> <cat> <file> <type>DM</type> <pin></pin> </file> </cat> <cat> <file> <type>CM</type> <pin></pin> </file> </cat> <cat> <file> <type>CM</type> <pin></pin> </file> </cat> </record> </root>
现有失效XSLT代码:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:template match="/record"> <root><xsl:for-each-group select="record" group-by="type"> <xsl:choose> <xsl:for-each-group select="record" group-by="pin"> <xsl:when test="current-grouping-key()"> <cat> <xsl:copy-of select="current-group()"/> </cat> </xsl:when></xsl:for-each-group> <xsl:otherwise> <cat> <xsl:copy-of select="."/> </cat> </xsl:otherwise> </xsl:choose> </xsl:for-each-group></root> </xsl:template> </xsl:stylesheet>
修正后的XSLT代码
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:template match="/"> <root> <record> <!-- 处理pin非空的file节点,按type+pin组合值分组 --> <xsl:for-each-group select="record/file[string(pin)]" group-by="concat(type, '|', pin)"> <cat> <xsl:copy-of select="current-group()"/> </cat> </xsl:for-each-group> <!-- 处理pin为空的file节点,每个节点单独生成cat --> <xsl:for-each select="record/file[not(string(pin))]"> <cat> <xsl:copy-of select="."/> </cat> </xsl:for-each> </record> </root> </xsl:template> </xsl:stylesheet>
代码说明
原代码的核心问题:
- 模板匹配错误:原模板匹配
/record,但文档根节点是/,无法完整处理整个文档 - 分组对象错误:原代码尝试对
record节点分组,实际需要分组的是record下的file节点 - 分组逻辑混乱:嵌套分组逻辑错误,未正确将
type和pin组合作为分组键,也未区分pin为空的场景
修正后的逻辑:
- 匹配文档根节点,构建输出的
root和record结构 - 第一部分:筛选
pin非空的file节点,用concat(type, '|', pin)作为分组键,确保相同type和pin的节点归为一组,每组生成一个<cat>节点并复制组内所有file - 第二部分:筛选
pin为空的file节点,逐个遍历并为每个节点单独生成<cat>节点
内容的提问来源于stack exchange,提问作者Nikita
相关产品推荐
相关产品推荐

