XSLT实现chargeto重复与唯一Customer记录分离求助
XSLT分组问题:按chargeto值分类Customer节点
问题描述
尝试了Key、for-each-group、match等多种XSLT方法均未生效。需求是将输入XML中chargeto值重复的<Customer>节点归入<Customer_PO>,值唯一的归入<Customer_Falty>,但自行编写的XSLT生成目标文件时出现数据丢失问题。
输入XML
<?xml version='1.0' encoding='UTF-8'?> <CustomerRecord> <Customer> <chargeto>ABC</chargeto> <chargename>GARY</chargename> </Customer> <Customer> <chargeto>XYZ</chargeto> <chargename>DAVIS</chargename> </Customer> <Customer> <chargeto>CDE</chargeto> <chargename>GARY DAVIS</chargename> </Customer> <Customer> <chargeto>ABC</chargeto> <chargename>DAV</chargename> </Customer> </CustomerRecord>
期望输出XML
<?xml version='1.0' encoding='UTF-8'?> <Root> <Customer_PO> <Customer> <chargeto>ABC</chargeto> <chargename>GARY</chargename> </Customer> <Customer> <chargeto>ABC</chargeto> <chargename>DAV</chargename> </Customer> </Customer_PO> <Customer_Falty> <Customer> <chargeto>XYZ</chargeto> <chargename>DAVIS</chargename> </Customer> <Customer> <chargeto>CDE</chargeto> <chargename>GARY DAVIS</chargename> </Customer> </Customer_Falty> </Root>
初始XSLT代码
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var" exclude-result-prefixes="msxsl var" version="1.0" xmlns:ns0="http://Namespace"> <xsl:output omit-xml-declaration="yes" method="xml" version="1.0" /> <xsl:key use="chargeto" match="/CustomerRecord/Customer" name ="groups"/> <xsl:template match="/"> <xsl:apply-templates select="/CustomerRecord" /> </xsl:template> <xsl:template match="/CustomerRecord"> <Root> <xsl:for-each select="/CustomerRecord/Customer[generate-id(.)=generate-id(key('groups',chargeto))]"> <Customer_PO> <xsl:for-each select="key('groups',chargeto)"> <Customer> <chargeto> <xsl:value-of select="CustomerRecord/chargeto/text()" /> </chargeto> <chargename> <xsl:value-of select="CustomerRecord/chargename/text()" /> </chargename> </Customer> </xsl:for-each> </Customer_PO> </xsl:for-each> </Root> </xsl:template> </xsl:stylesheet>
问题分析与修正方案
原代码问题点
- 路径错误:循环
<Customer>节点时,使用CustomerRecord/chargeto/text()是错误的,当前上下文已是<Customer>,直接引用子元素即可。 - 缺少唯一值处理:仅生成了
<Customer_PO>,未处理chargeto值唯一的节点(即<Customer_Falty>部分)。 - 分组逻辑未区分组大小:未判断分组内节点数量,导致所有分组都被放入
<Customer_PO>。
修正后的XSLT代码
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <!-- 按chargeto值分组 --> <xsl:key name="customer-group" match="CustomerRecord/Customer" use="chargeto"/> <xsl:template match="/"> <Root> <!-- 处理重复chargeto的节点,归入Customer_PO --> <Customer_PO> <xsl:for-each select="CustomerRecord/Customer[generate-id(.) = generate-id(key('customer-group', chargeto)) and count(key('customer-group', chargeto)) > 1]"> <xsl:copy-of select="key('customer-group', chargeto)"/> </xsl:for-each> </Customer_PO> <!-- 处理唯一chargeto的节点,归入Customer_Falty --> <Customer_Falty> <xsl:for-each select="CustomerRecord/Customer[generate-id(.) = generate-id(key('customer-group', chargeto)) and count(key('customer-group', chargeto)) = 1]"> <xsl:copy-of select="key('customer-group', chargeto)"/> </xsl:for-each> </Customer_Falty> </Root> </xsl:template> </xsl:stylesheet>
代码说明
- 使用
<xsl:copy-of>直接复制符合条件的<Customer>节点,避免手动构造节点时的路径错误。 - 通过
count(key('customer-group', chargeto))判断分组大小:- 数量>1的分组放入
<Customer_PO> - 数量=1的分组放入
<Customer_Falty>
- 数量>1的分组放入
- 简化模板结构,直接在根模板中完成所有逻辑,减少不必要的模板调用。
内容的提问来源于stack exchange,提问作者ABC
相关产品推荐
相关产品推荐

