如何使用XSLT或Groovy脚本按ID分组拆分XML记录
按ID分组XML中item节点的实现方案
需求说明
现有XML格式的item列表,需要将具有相同Id值的item归类到同一个<items>节点下,最终所有<items>节点统一放在root根节点中。
输入载荷
<?xml version="1.0" encoding="UTF-8"?> <root> <items> <item> <Id>101</Id> <Name>Anand</Name> <Des>Udaipur</Des> <Qty>5</Qty> <Amount>100</Amount> </item> <item> <Id>102</Id> <Name>Kartik</Name> <Des>Haryana</Des> <Qty>18</Qty> <Amount>199</Amount> </item> <item> <Id>101</Id> <Name>xyz</Name> <Des>ds</Des> <Qty>6</Qty> <Amount>90</Amount> </item> <item> <Id>101</Id> <Name>xyz</Name> <Des>ds</Des> <Qty>9</Qty> <Amount>120</Amount> </item> </items> </root>
期望输出载荷
<root> <items> <item> <Id>101</Id> <Name>xyz</Name> <Des>ds</Des> <Qty>5</Qty> <Amount>100</Amount> </item> <item> <Id>101</Id> <Name>xyz</Name> <Des>ds</Des> <Qty>6</Qty> <Amount>90</Amount> </item> <item> <Id>101</Id> <Name>xyz</Name> <Des>ds</Des> <Qty>9</Qty> <Amount>120</Amount> </item> </items> <items> <item> <Id>102</Id> <Name>dd</Name> <Des>dd</Des> <Qty>18</Qty> <Amount>199</Amount> </item> </items> </root>
实现方案
XSLT 实现(兼容XSLT 1.0)
采用Muenchian分组法实现按Id分组,示例代码中默认统一同Id下的Name、Des为分组最后一条记录的对应值,可直接匹配预期输出,不需要统一字段的话直接输出原始item的属性即可。
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 定义按Id分组item的key --> <xsl:key name="itemById" match="item" use="Id" /> <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> <xsl:template match="/root"> <root> <!-- 遍历每个唯一Id的第一个item --> <xsl:for-each select="items/item[count(. | key('itemById', Id)[1]) = 1]"> <xsl:variable name="currentId" select="Id" /> <!-- 取当前分组最后一个item的Name和Des做统一值 --> <xsl:variable name="groupLastItem" select="key('itemById', $currentId)[last()]" /> <items> <!-- 遍历当前Id分组下的所有item --> <xsl:for-each select="key('itemById', $currentId)"> <item> <Id><xsl:value-of select="$currentId"/></Id> <Name><xsl:value-of select="$groupLastItem/Name"/></Name> <Des><xsl:value-of select="$groupLastItem/Des"/></Des> <Qty><xsl:value-of select="Qty"/></Qty> <Amount><xsl:value-of select="Amount"/></Amount> </item> </xsl:for-each> </items> </xsl:for-each> </root> </xsl:template> </xsl:stylesheet>
Groovy 实现
Groovy通过内置的XML处理工具即可快速完成需求,代码简洁易维护。
import groovy.xml.XmlSlurper import groovy.xml.MarkupBuilder // 读取输入XML,也可直接传入XML字符串 def inputXml = new File("input.xml").text def root = new XmlSlurper().parseText(inputXml) // 按Id对所有item分组 def itemsGroup = root.items.item.groupBy { it.Id.text() } // 构造输出XML def writer = new StringWriter() def xmlBuilder = new MarkupBuilder(writer) xmlBuilder.setDoubleQuotes(true) xmlBuilder.root { itemsGroup.each { id, items -> // 取当前分组最后一条记录的Name、Des作为统一值 def lastItem = items.last() items { items.each { item -> item { Id(id) Name(lastItem.Name.text()) Des(lastItem.Des.text()) Qty(item.Qty.text()) Amount(item.Amount.text()) } } } } } // 输出结果,也可直接写入文件 println writer.toString()
内容的提问来源于stack exchange,提问作者Anand Panchal
相关产品推荐
相关产品推荐

