XSLT 1.0技术问询:如何合并两个兄弟元素中的customer_id并生成唯一分组
解决XML/XSLT中合并不同位置customer_id并生成唯一列表的问题
嘿,作为XML/XSLT初学者能做到这一步已经很棒啦!咱们来搞定这个customer_id去重的问题。你的核心痛点是:不同类型的工单(HelpRequest/ServiceRequest)里,customer_id所在的位置不一样——HelpRequest在第2个<string>,ServiceRequest在第3个<string>,所以得先统一获取每个工单对应的customer_id,再用Muenchian方法去重生成唯一列表。
解决方案步骤
1. 正确定义customer_id的key
首先修改你的key定义,针对每个<row>,根据工单类型动态获取对应的customer_id值作为key的索引:
<xsl:key name="customer_id" match="row" use="if (*[4] = 'HelpRequest') then *[2] else *[3]"/>
这里match="row"是因为每个<row>对应一个customer_id;use部分通过判断第4个元素的值(工单类型),决定取第2个还是第3个<string>的值。
2. 用Muenchian方法生成唯一customer列表
替换你注释掉的customer部分代码,这样就能筛选出每个唯一customer_id的第一个实例:
<xsl:for-each select="result/row[generate-id() = generate-id(key('customer_id', if (*[4] = 'HelpRequest') then *[2] else *[3])[1])]"> <customer> <customer_id> <xsl:value-of select="if (*[4] = 'HelpRequest') then *[2] else *[3]"/> </customer_id> </customer> </xsl:for-each>
修改后的完整XSLT代码
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:key name="support_id" match="row" use="*[6]"/> <xsl:key name="support_grp_id" match="row" use="*[7]"/> <xsl:key name="company_id" match="row" use="*[5]"/> <!-- 新增的customer_id key定义 --> <xsl:key name="customer_id" match="row" use="if (*[4] = 'HelpRequest') then *[2] else *[3]"/> <xsl:template match="/"> <data> <!-- 生成work_order部分(保留你原有的逻辑) --> <xsl:for-each select="result/row"> <xsl:if test="*[4] = 'HelpRequest'"> <work_order> <work_order_id><xsl:value-of select = "*[1]"/></work_order_id> <customer_id><xsl:value-of select = "*[2]"/></customer_id> <work_type><xsl:value-of select = "*[4]"/></work_type> <company_id><xsl:value-of select = "*[5]"/></company_id> <support_id><xsl:value-of select = "*[6]"/></support_id> <support_grp_id><xsl:value-of select = "*[7]"/></support_grp_id> </work_order> </xsl:if> <xsl:if test="*[4] = 'ServiceRequest'"> <work_order> <work_order_id><xsl:value-of select = "*[1]"/></work_order_id> <customer_id><xsl:value-of select = "*[3]"/></customer_id> <work_type><xsl:value-of select = "*[4]"/></work_type> <company_id><xsl:value-of select = "*[5]"/></company_id> <support_id><xsl:value-of select = "*[6]"/></support_id> <support_grp_id><xsl:value-of select = "*[7]"/></support_grp_id> </work_order> </xsl:if> </xsl:for-each> <!-- support部分(优化match目标为row更准确) --> <xsl:for-each select="result/row[generate-id() = generate-id(key('support_id',*[6])[1])]"> <support> <support_id><xsl:value-of select = "*[6]"/></support_id> </support> </xsl:for-each> <!-- support_grp部分 --> <xsl:for-each select="result/row[generate-id() = generate-id(key('support_grp_id',*[7])[1])]"> <support_grp> <support_grp_id><xsl:value-of select = "*[7]"/></support_grp_id> </support_grp> </xsl:for-each> <!-- company部分 --> <xsl:for-each select="result/row[generate-id() = generate-id(key('company_id',*[5])[1])]"> <company> <company_id><xsl:value-of select = "*[5]"/></company_id> </company> </xsl:for-each> <!-- 新增的customer唯一列表部分 --> <xsl:for-each select="result/row[generate-id() = generate-id(key('customer_id', if (*[4] = 'HelpRequest') then *[2] else *[3])[1])]"> <customer> <customer_id> <xsl:value-of select="if (*[4] = 'HelpRequest') then *[2] else *[3]"/> </customer_id> </customer> </xsl:for-each> </data> </xsl:template> </xsl:transform>
验证结果
用这个XSLT转换你的源XML,就能得到你期望的结果:生成包含所有工单,以及唯一的support、support_grp、company、customer列表的XML,其中customer列表会正确合并PER-013、PER-017、PER-029、PER-024这四个唯一值。
内容的提问来源于stack exchange,提问作者Teijo Sipilä
相关产品推荐
相关产品推荐

