请求:基于XSLT 1.0/2.0实现XML按规则分组转换
XML转换需求:基于
format属性分组合并CommissionEvent节点 输入XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <ns2:CommissionEvents xmlns="urn:tracelink:mapper:sl:canonical:commontypes" xmlns:ns2="urn:tracelink:mapper:sl:canonical:serialized_operations_manager"> <ns2:CommissionEvent> <NumberList> <Serial barcodeContent="(01)00355135132011(21)897883089643(17)230430(10)TLSMKTST" companyPrefix="0355135" filterValue="0" format="AI(01)+AI(21)">010035513513201121897883089643</Serial> </NumberList> </ns2:CommissionEvent> <ns2:CommissionEvent> <NumberList> <Serial barcodeContent="(01)00355135132011(21)903131477120(17)230430(10)TLSMKTST" companyPrefix="0355135" filterValue="0" format="AI(01)+AI(21)">010035513513201121903131477120</Serial> </NumberList> </ns2:CommissionEvent> <ns2:CommissionEvent> <NumberList> <Serial barcodeContent="(01)30355135132012(21)389170110454(17)230430(10)TLSMKTST" companyPrefix="0355135" filterValue="3" format="AI(01)+AI(21)">013035513513201221389170110454</Serial> </NumberList> </ns2:CommissionEvent> <ns2:CommissionEvent> <NumberList> <Serial barcodeContent="(00)003551350000000907" companyPrefix="0355135" filterValue="0" format="AI(00)">00003551350000000907</Serial> </NumberList> </ns2:CommissionEvent> <ns2:CommissionEvent> <NumberList> <Serial barcodeContent="(00)103551350000000645" companyPrefix="0355135" filterValue="1" format="AI(00)">00103551350000000645</Serial> </NumberList> </ns2:CommissionEvent> </ns2:CommissionEvents>
期望输出XML
<ns2:CommissionEvents> <ns2:CommissionEvent> <ns0:NumberList> <ns0:Serial barcodeContent="(01)00355135132011(21)897883089643(17)230430(10)TLSMKTST" companyPrefix="0355135" filterValue="0" format="AI(01)+AI(21)" /> <ns0:Serial barcodeContent="(01)00355135132011(21)903131477120(17)230430(10)TLSMKTST" companyPrefix="0355135" filterValue="0" format="AI(01)+AI(21)" /> </ns0:NumberList> </ns2:CommissionEvent> <ns2:CommissionEvent> <ns0:NumberList> <ns0:Serial barcodeContent="(01)30355135132012(21)389170110454(17)230430(10)TLSMKTST" companyPrefix="0355135" filterValue="3" format="AI(01)+AI(21)" /> </ns0:NumberList> </ns2:CommissionEvent> <ns2:CommissionEvent> <ns0:NumberList> <ns0:Serial barcodeContent="(00)003551350000000907" companyPrefix="0355135" filterValue="0" format="AI(00)" /> <ns0:Serial barcodeContent="(00)103551350000000645" companyPrefix="0355135" filterValue="1" format="AI(00)" /> </ns0:NumberList> </ns2:CommissionEvent> </ns2:CommissionEvents>
解决方案
XSLT 2.0 实现方案
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns2="urn:tracelink:mapper:sl:canonical:serialized_operations_manager" xmlns:ns0="urn:tracelink:mapper:sl:canonical:commontypes" exclude-result-prefixes="ns2 ns0"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/ns2:CommissionEvents"> <ns2:CommissionEvents> <!-- 按Serial节点的format属性分组 --> <xsl:for-each-group select="ns2:CommissionEvent/NumberList/Serial" group-by="@format"> <ns2:CommissionEvent> <ns0:NumberList> <!-- 遍历分组内的Serial,转为自闭合标签并添加ns0前缀 --> <xsl:for-each select="current-group()"> <ns0:Serial> <xsl:copy-of select="@*"/> </ns0:Serial> </xsl:for-each> </ns0:NumberList> </ns2:CommissionEvent> </xsl:for-each-group> </ns2:CommissionEvents> </xsl:template> </xsl:stylesheet>
XSLT 1.0 实现方案(Muenchian分组)
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns2="urn:tracelink:mapper:sl:canonical:serialized_operations_manager" xmlns:ns0="urn:tracelink:mapper:sl:canonical:commontypes" exclude-result-prefixes="ns2 ns0"> <xsl:output method="xml" indent="yes"/> <!-- 定义分组键:Serial的format属性 --> <xsl:key name="serial-by-format" match="ns2:CommissionEvent/NumberList/Serial" use="@format"/> <xsl:template match="/ns2:CommissionEvents"> <ns2:CommissionEvents> <!-- 遍历所有唯一的format分组 --> <xsl:for-each select="ns2:CommissionEvent/NumberList/Serial[generate-id() = generate-id(key('serial-by-format', @format)[1])]"> <ns2:CommissionEvent> <ns0:NumberList> <!-- 输出当前分组内的所有Serial节点 --> <xsl:for-each select="key('serial-by-format', @format)"> <ns0:Serial> <xsl:copy-of select="@*"/> </ns0:Serial> </xsl:for-each> </ns0:NumberList> </ns2:CommissionEvent> </xsl:for-each> </ns2:CommissionEvents> </xsl:template> </xsl:stylesheet>
核心逻辑说明
- 两种方案均基于
Serial节点的format属性进行分组,将同格式的Serial合并到同一个CommissionEvent节点下。 - 移除原
Serial节点的文本内容,转换为自闭合标签,并为NumberList和Serial添加ns0前缀(对应原默认命名空间)。 - XSLT 2.0使用
for-each-group语法更简洁,XSLT 1.0通过Muenchian分组实现相同效果。
内容的提问来源于stack exchange,提问作者user6927606
相关产品推荐
相关产品推荐

