XSLT实现XML ID去重并动态添加元素的技术问题
解决XSLT按ID分组并关联price和country的问题
嘿,看来你卡在XSLT分组关联数据这一步了!别担心,这是处理重复节点时很常见的需求,我给你两种解决方案,分别适配不同版本的XSLT,帮你把带重复ID的data节点按ID分组,同时正确关联对应的price和country元素。
先明确你的需求场景(示例)
假设你的源XML是这样的:
<root> <data> <id>1</id> <price>10.99</price> <country>US</country> </data> <data> <id>1</id> <price>12.99</price> <country>CA</country> </data> <data> <id>2</id> <price>15.99</price> <country>UK</country> </data> </root>
你期望的目标XML结构:
<Products> <Product> <id>1</id> <prices> <price country="US">10.99</price> <price country="CA">12.99</price> </prices> </Product> <Product> <id>2</id> <prices> <price country="UK">15.99</price> </prices> </Product> </Products>
方案1:XSLT 1.0(Muenchian分组法)
XSLT 1.0没有原生的分组语法,所以经典的解决方案是用Muenchian分组,通过定义键来实现分组:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <!-- 定义键:按data节点的id值分组 --> <xsl:key name="data-by-id" match="data" use="id"/> <xsl:template match="/root"> <Products> <!-- 筛选出每个ID组的第一个节点(即去重后的唯一ID) --> <xsl:for-each select="data[count(. | key('data-by-id', id)[1]) = 1]"> <Product> <id><xsl:value-of select="id"/></id> <prices> <!-- 遍历当前ID对应的所有data节点,获取price和country --> <xsl:for-each select="key('data-by-id', id)"> <price country="{country}"> <xsl:value-of select="price"/> </price> </xsl:for-each> </prices> </Product> </xsl:for-each> </Products> </xsl:template> </xsl:stylesheet>
关键逻辑解释:
<xsl:key>:创建一个名为data-by-id的键,匹配所有data节点,以id的值作为分组依据。data[count(. | key('data-by-id', id)[1]) = 1]:这个表达式用来筛选每个分组的第一个节点(也就是去重后的唯一ID),确保每个ID只处理一次。key('data-by-id', id):通过当前ID,获取该分组下的所有data节点,这样就能拿到对应的price和country了。
方案2:XSLT 2.0+(原生分组语法)
如果你的环境支持XSLT 2.0及以上版本,那可以直接用原生的<xsl:for-each-group>语法,代码更简洁易懂:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/root"> <Products> <!-- 按data节点的id值分组 --> <xsl:for-each-group select="data" group-by="id"> <Product> <!-- 获取当前分组的ID值 --> <id><xsl:value-of select="current-grouping-key()"/></id> <prices> <!-- 遍历当前分组下的所有data节点 --> <xsl:for-each select="current-group()"> <price country="{country}"> <xsl:value-of select="price"/> </price> </xsl:for-each> </prices> </Product> </xsl:for-each-group> </Products> </xsl:template> </xsl:stylesheet>
关键逻辑解释:
<xsl:for-each-group select="data" group-by="id">:直接指定按id对data节点分组。current-grouping-key():返回当前分组的键值(也就是当前的ID)。current-group():返回当前分组下的所有data节点,轻松获取每个节点的price和country。
这两种方案都能完美实现你要的按ID分组并关联对应数据的需求,你可以根据自己的XSLT版本选择合适的代码~
内容的提问来源于stack exchange,提问作者Daniel Fagerberg
相关产品推荐
相关产品推荐

