如何用XSLT 1.0匹配元素并计算XML值的除法运算
问题描述
我尝试对XML中ID和Date匹配的两条记录的Value值进行除法运算,但无法引用第二条记录的值。
源XML:
<Export> <Record> <ID>1000</ID> <Date>2022-08-15</Date> <Value>14.09059</Value> </Record> <Record> <ID>1000</ID> <Date>2022-08-15</Date> <Value>259.394</Value> </Record> <Record> <ID>2000</ID> <Date>2022-08-08</Date> <Value>32.01453</Value> </Record> <Record> <ID>2000</ID> <Date>2022-08-08</Date> <Value>467.052</Value> </Record> </Export>
期望输出:
<Export> <Record> <ID>1000</ID> <Date>2022-08-15</Date> <Value>18.409</Value> </Record> <Record> <ID>2000</ID> <Date>2022-08-08</Date> <Value>14.589</Value> </Record> </Export>
请问这能否通过XSLT 1.0实现?
解决方案:XSLT 1.0实现
可以通过XSLT 1.0的Muenchian分组技术实现需求,核心是按ID+Date的组合对记录分组,再在每组内完成除法运算并格式化结果。
以下是完整的XSLT代码:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <!-- 定义分组键:用|分隔ID和Date,避免内容拼接冲突 --> <xsl:key name="record-group" match="Record" use="concat(ID, '|', Date)"/> <xsl:template match="/Export"> <Export> <!-- 仅处理每组的第一个节点,避免重复输出 --> <xsl:for-each select="Record[generate-id() = generate-id(key('record-group', concat(ID, '|', Date))[1])]"> <Record> <!-- 复制ID和Date节点 --> <xsl:copy-of select="ID | Date"/> <Value> <!-- 获取组内两个Value值,计算商并保留三位小数 --> <xsl:value-of select="format-number( key('record-group', concat(ID, '|', Date))[2]/Value div key('record-group', concat(ID, '|', Date))[1]/Value, '0.000' )"/> </Value> </Record> </xsl:for-each> </Export> </xsl:template> </xsl:stylesheet>
代码说明
- 分组逻辑:通过
<xsl:key>定义分组规则,将ID和Date拼接成唯一键,确保同一组合的记录被分到一组。 - 去重遍历:用
generate-id()判断当前节点是否为组内第一个节点,仅处理一次每组记录,避免重复输出。 - 运算与格式化:通过
key()获取组内的两个Value节点,执行除法后用format-number()将结果格式化为三位小数,匹配期望输出格式。
注意事项
- 代码默认每组固定两条记录,若存在更多记录,需调整索引逻辑或通过排序取最大/最小值进行计算;若仅需最大值除以最小值,XSLT1.0可通过排序实现该逻辑。
内容的提问来源于stack exchange,提问作者Ali Reza Amirsardari
相关产品推荐
相关产品推荐

