XML节点分组与合并需求:将Sequence等归入Benefit并按Coverage合并Row
使用XSLT实现XML结构转换与分组
需求概述
需要将原XML中带数字后缀的SequenceN/QualifierN/DateN元素,封装到Benefit节点中;同时按Coverage元素的值合并对应的Row,并重新编排Sequence的序号。
实现方案(XSLT 2.0)
以下是完成转换的XSLT代码:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <!-- 按Coverage值分组Row节点 --> <xsl:key name="row-by-coverage" match="Row" use="Coverage"/> <xsl:template match="/Root"> <Root> <!-- 遍历每个Coverage分组 --> <xsl:for-each-group select="Row" group-by="Coverage"> <Row> <!-- 保留Coverage和Admission元素 --> <xsl:copy-of select="Coverage"/> <xsl:copy-of select="Admission"/> <Benefits> <!-- 遍历分组内所有Row中的带数字后缀的元素,按数字后缀排序 --> <xsl:for-each select="current-group()/*[matches(local-name(), '^(Sequence|Qualifier|Date)\d+$')]"> <xsl:sort select="replace(local-name(), '^(Sequence|Qualifier|Date)(\d+)$', '$2')" data-type="number"/> <xsl:sort select="generate-id(..)"/> <!-- 每3个元素为一组生成Benefit --> <xsl:if test="position() mod 3 = 1"> <Benefit> <!-- 生成全局连续的Sequence序号 --> <Sequence> <xsl:number count="current-group()/*[matches(local-name(), '^Sequence\d+$')]" from="Root"/> </Sequence> <!-- 匹配同数字后缀的Qualifier --> <Qualifier> <xsl:value-of select="../*[local-name() = concat('Qualifier', replace(local-name(current()), '^Sequence(\d+)$', '$1'))]"/> </Qualifier> <!-- 匹配同数字后缀的Date --> <Date> <xsl:value-of select="../*[local-name() = concat('Date', replace(local-name(current()), '^Sequence(\d+)$', '$1'))]"/> </Date> </Benefit> </xsl:if> </xsl:for-each> </Benefits> </Row> </xsl:for-each-group> </Root> </xsl:template> </xsl:stylesheet>
关键逻辑说明
- 分组合并Row:通过
<xsl:key>和<xsl:for-each-group>按Coverage的值将原始Row合并为同一个Row节点,确保相同Coverage的记录聚合在一起。 - 提取并封装Benefit:用正则匹配识别带数字后缀的元素,按数字后缀将
SequenceN/QualifierN/DateN三组元素封装成单个Benefit节点。 - Sequence重新编号:通过
<xsl:number>对所有Sequence元素进行全局计数,生成连续的序号(如示例中Partial分组的Sequence从1到4)。 - 结构保留:原样保留原
Coverage和Admission元素的内容与位置,保证输出结构符合预期。
使用方式
将上述XSLT代码与你的输入XML文件一起,通过支持XSLT 2.0的工具(如Saxon、Altova XMLSpy等)执行转换,即可得到目标输出XML。
内容的提问来源于stack exchange,提问作者Ram
相关产品推荐
相关产品推荐

