如何使用xslt基于多个属性的组合删除重复元素

时间:2015-02-16 06:12:26

标签: xml xslt

这就是我的输入XML的样子:

<?xml version="1.0" encoding="UTF-8"?>
<root>
<Account  InceptionDate="03/01/2005"  BusinessWorkGroup="US" BusinessUnit="BOS" AccountId="XYZ4321" ISOCurrency="USD" DomicileCountry="USA">
<AssignContact ContactId="123" Type="Administrative Assistant"/>
<AssignContact ContactId="123" Type="Portfolio Manager"/>
<AssignContact ContactId="123" Type="Portfolio Manager"/>
</Account>  
<Account  InceptionDate="03/01/2006"  BusinessWorkGroup="US" BusinessUnit="BOS" AccountId="ABC1231" ISOCurrency="USD" DomicileCountry="USA">
<AssignContact ContactId="543" Type="Administrative Assistant"/>
<AssignContact ContactId="543" Type="Portfolio Manager"/>
<AssignContact ContactId="211" Type="Portfolio Manager"/>
</Account>  
<Account  InceptionDate="03/01/2010"  BusinessWorkGroup="US" BusinessUnit="BOS" AccountId="DUM111" ISOCurrency="USD" DomicileCountry="USA">
<AssignContact ContactId="987" Type="Administrative Assistant"/>
<AssignContact ContactId="987" Type="Administrative Assistant"/>
<AssignContact ContactId="211" Type="Portfolio Manager"/>
</Account> 
</root>

我的输出应如下所示:(对于每个AccountId - 应从最终的xml中删除重复的[ContactId&amp; Type的组合]):

<?xml version="1.0" encoding="UTF-8"?>
<root>
<Account  InceptionDate="03/01/2005"  BusinessWorkGroup="US" BusinessUnit="BOS" AccountId="XYZ4321" ISOCurrency="USD" DomicileCountry="USA">
<AssignContact ContactId="123" Type="Administrative Assistant"/>
<AssignContact ContactId="123" Type="Portfolio Manager"/>
</Account>  
<Account  InceptionDate="03/01/2006"  BusinessWorkGroup="US" BusinessUnit="BOS" AccountId="ABC1231" ISOCurrency="USD" DomicileCountry="USA">
<AssignContact ContactId="543" Type="Administrative Assistant"/>
<AssignContact ContactId="543" Type="Portfolio Manager"/>
<AssignContact ContactId="211" Type="Portfolio Manager"/>
</Account>
<Account  InceptionDate="03/01/2010"  BusinessWorkGroup="US" BusinessUnit="BOS" AccountId="DUM111" ISOCurrency="USD" DomicileCountry="USA">
<AssignContact ContactId="987" Type="Administrative Assistant"/>
<AssignContact ContactId="211" Type="Portfolio Manager"/>
</Account> 
</root>

我正在使用的XSLT工作不正常,请让我知道如何修改我的xsl,以便它也可以与ContactId一起查找Type

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0" >
<xsl:output method="xml" indent="yes" version="1.0"/>
<xsl:strip-space elements="*"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="AssignContact">
    <xsl:if test="not(@ContactId=preceding-sibling::AssignContact/@ContactId)">
      <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

1 个答案:

答案 0 :(得分:1)

评论中提供的链接是一种名为&#34; Muenchian Grouping&#34;的技术。在您的情况下,您希望按其父AssignContact及其AccountIdContactId属性对TypeId进行分组。这意味着使用连接密钥。

<xsl:key name="Contact" 
         match="AssignContact" 
         use="concat(../@AccountId, '|', @ContactId, '|', @Type)" />

请注意,您不必在此处提供AssignContact的完整路径。另请注意使用|管道符分隔参数。你可以在这里使用任何字符,只要它不会出现在你连接的任何字符串中。

接下来要提到的是,因为您在此处使用身份模板,所以您不必担心复制其他模板中的现有节点。您只需要从要删除的节点中编写模板。在您的情况下,您希望删除已经发生组合AssignContactAccountIdContactId属性的TypeId个节点。使用Muenchian分组,表达式如下:

<xsl:template match="AssignContact
                     [generate-id() != generate-id(key('Contact', concat(../@AccountId, '|', @ContactId, '|', @Type))[1])]" />

试试这个XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" >
    <xsl:output method="xml" indent="yes" version="1.0"/>
    <xsl:strip-space elements="*"/>

    <xsl:key name="Contact" match="AssignContact" use="concat(@ContactId, '|', @Type)" />

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
    </xsl:template>

    <xsl:template match="AssignContact[generate-id() != generate-id(key('Contact', concat(../@AccountId, '|', @ContactId, '|', @Type))[1])]" />
</xsl:stylesheet>