如何将基于XSLT 2.0 for-each-group的SDMX数据分组逻辑转换为XSLT 1.0实现
如何将基于XSLT 2.0 for-each-group的SDMX数据分组逻辑转换为XSLT 1.0实现
嗨,我完全懂你的感受——XSLT 2.0的for-each-group用起来简直太顺手了,结果遇到只支持1.0的应用就卡壳了。别着急,咱们用XSLT 1.0里的Muenchian分组法就能完美复刻你原来的逻辑,下面我给你一步步拆解实现:
核心思路:Muenchian分组替代for-each-group
XSLT 1.0没有原生的分组指令,Muenchian分组是业界通用的解决方案,核心是通过<xsl:key>定义分组规则,再通过generate-id()筛选出唯一的分组键,最后遍历这些键来处理每组数据。
适配你的SDMX数据的具体实现
首先要注意:XSLT 1.0不支持xpath-default-namespace,所以咱们得给XML里的命名空间都加上前缀,避免节点匹配出错。
下面是完整的XSLT 1.0代码,和你原来的2.0逻辑完全对应:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:generic="http://www.sdmx.org/resources/sdmxml/schemas/v2_1/data/generic" xmlns:ns1="http://tempuri.org/ns1" <!-- 可根据实际需求调整命名空间 --> exclude-result-prefixes="generic"> <xsl:output indent="yes"/> <!-- 定义分组键:按Obs的时间维度值分组 --> <xsl:key name="grouped-obs" match="generic:Obs" use="generic:ObsDimension/@value"/> <xsl:template match="/"> <ns1:DiscountInterestRatePercent xmlns:xslt-version="MonthlyDiscounts_XSLT_26/06/2022"> <!-- 遍历所有唯一的时间维度值(对应原2.0的group-by) --> <xsl:for-each select="//generic:Series[generic:SeriesKey/generic:Value/@value='ABZINS7']/generic:Obs[generate-id() = generate-id(key('grouped-obs', generic:ObsDimension/@value)[1])]"> <!-- 按时间维度值排序,保证输出顺序和原逻辑一致 --> <xsl:sort select="generic:ObsDimension/@value"/> <Data> <Year> <xsl:value-of select="substring-before(generic:ObsDimension/@value, '-')"/> </Year> <Month> <xsl:value-of select="substring-after(generic:ObsDimension/@value, '-')"/> </Month> <RatePercentList> <!-- 遍历当前分组下的所有Obs节点(对应原2.0的current-group()) --> <xsl:for-each select="key('grouped-obs', generic:ObsDimension/@value)"> <RatePercent> <xsl:value-of select="generic:ObsValue/@value"/> </RatePercent> </xsl:for-each> </RatePercentList> </Data> </xsl:for-each> </ns1:DiscountInterestRatePercent> </xsl:template> </xsl:stylesheet>
关键部分说明
<xsl:key>:定义了分组规则,把所有generic:Obs节点按ObsDimension的value属性分组,名字叫grouped-obs。- 筛选唯一分组键:通过
generate-id() = generate-id(key('grouped-obs', generic:ObsDimension/@value)[1]),只保留每个分组里的第一个节点,这样就得到了所有唯一的时间维度值。 - 遍历分组内容:用
key('grouped-obs', generic:ObsDimension/@value)获取当前时间维度对应的所有Obs节点,这就相当于XSLT 2.0里的current-group()。 - 排序:我额外加了
<xsl:sort>来保证输出的时间顺序和原逻辑一致,你可以根据需求调整排序规则。
这个代码处理你的SDMX输入XML后,输出结果会和你原来的XSLT 2.0代码完全一样,完美适配只支持1.0的应用。
备注:内容来源于stack exchange,提问作者Sateesh
相关产品推荐
相关产品推荐

