首页 > 解决方案 > 根据条件删除重复项

问题描述

我正在尝试根据 XSLT1.0 中的条件从我的 xml 中删除重复项

这是输入的xml。

<?xml version="1.0" encoding="UTF-8"?>
<Envelope
    xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
    <Header>
        <MessageId>{D5B72T7A-58E0-4930-9CEB-A06RT56AR21B0}</MessageId>
        <Action>http://tempuri.org/TRH_FinalQueryService/find</Action>
    </Header>
    <Body>
        <MessageParts
            xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
            <TRH_FinalQuery
                xmlns="http://schemas.microsoft.com/dynamics/2008/01/documents/TRH_FinalQuery">
                <TRH_UnionView class="entity">
                    <Company>1</Company>
                    <CS/>
                    <Text_1>1</Text_1>
                    <Text_2>Lotion</Text_2>
                    <WS/>
                </TRH_UnionView>
                <TRH_UnionView class="entity">
                    <Company>1</Company>
                    <CS>1</CS>
                    <Text_1>1</Text_1>
                    <Text_2>Soap</Text_2>
                    <WS>6</WS>
                </TRH_UnionView>
                <TRH_UnionView class="entity">
                    <Company>2</Company>
                    <CS/>
                    <Text_1>5</Text_1>
                    <Text_2>Shampoo</Text_2>
                    <WS/>
                </TRH_UnionView>
                   <TRH_UnionView class="entity">
                    <Company>2</Company>
                    <CS/>
                    <Text_1>5</Text_1>
                    <Text_2>Shampoo</Text_2>
                    <WS/>
                </TRH_UnionView>
                   </TRH_FinalQuery>
        </MessageParts>
    </Body>
</Envelope>

这是我申请的xslt。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:m="http://schemas.microsoft.com/dynamics/2011/01/documents/Message" xmlns:r="http://schemas.microsoft.com/dynamics/2008/01/documents/TRH_FinalQuery" exclude-result-prefixes="m r">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
  <xsl:strip-space elements="*" />
  <xsl:key name="r:TRH_FinalQuery" match="r:TRH_FinalQuery" use="concat(r:Text_1, '|', r:Company)" />
  <!-- move all elements to no namespace -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="r:TRH_FinalQuery[r:TRH_UnionView[@class='entity']/r:WessexCostCenter=''][key('r:TRH_FinalQuery',concat(r:Text_1, '|', r:Company))[1]]"/>
  <xsl:template match="*">
    <xsl:element name="{local-name()}">
      <xsl:copy-of select="@*" />
      <xsl:apply-templates />
    </xsl:element>
  </xsl:template>
  <!-- removes Envelope -->
  <xsl:template match="m:Envelope">
    <xsl:apply-templates />
  </xsl:template>
  <!-- removes Header,MessageId,Action and Body -->
  <xsl:template match="m:*">
    <xsl:apply-templates select="*" />
  </xsl:template>
  <!-- rename MessageParts to Document + skip the Run wrapper -->
  <xsl:template match="m:MessageParts">
    <DocumentElement>
      <xsl:apply-templates select="r:TRH_FinalQuery/*" />
    </DocumentElement>
  </xsl:template>
  <!-- rename RunObject to Item -->
  <xsl:template match="r:TRH_UnionView[@class='entity']">
    <xsl:choose>
      <xsl:when test="r:WS!=''">

        <Item>
          <Text_1>
            <xsl:value-of select="r:WS" />
          </Text_1>
          <Text_2>WS BodayWash</Text_2>
          <Company>
            <xsl:value-of select="r:Text_1" />
          </Company>
        </Item>
        <Item>
          <Text_1>
            <xsl:value-of select="r:WS" />
          </Text_1>
          <Text_2>WS BodayWash</Text_2>
          <Company>0123</Company>
        </Item>

      </xsl:when>

      <xsl:otherwise>

        <Item>

          <xsl:apply-templates select="r:Text_1" />
          <xsl:apply-templates select="r:Text_2" />
          <xsl:apply-templates select="r:Company" />
        </Item>
        <Item>
          <xsl:apply-templates select="r:Text_1" />
          <xsl:apply-templates select="r:Text_2" />
          <Company>0123</Company>
        </Item>

      </xsl:otherwise>

    </xsl:choose>

  </xsl:template>
</xsl:stylesheet>

下面是我得到的输出

<?xml version="1.0" encoding="utf-8"?>
<DocumentElement>
  <Item>
    <Text_1>1</Text_1>
    <Text_2>Lotion</Text_2>
    <Company>1</Company>
  </Item>
  <Item>
    <Text_1>1</Text_1>
    <Text_2>Lotion</Text_2>
    <Company>0123</Company>
  </Item>
  <Item>
    <Text_1>6</Text_1>
    <Text_2>WS BodayWash</Text_2>
    <Company>1</Company>
  </Item>
  <Item>
    <Text_1>6</Text_1>
    <Text_2>WS BodayWash</Text_2>
    <Company>0123</Company>
  </Item>
  <Item>
    <Text_1>5</Text_1>
    <Text_2>Shampoo</Text_2>
    <Company>2</Company>
  </Item>
  <Item>
    <Text_1>5</Text_1>
    <Text_2>Shampoo</Text_2>
    <Company>0123</Company>
  </Item>
</DocumentElement>

下面是预期的输出

<?xml version="1.0" encoding="utf-8"?>
<DocumentElement>
  <Item>
    <Text_1>6</Text_1>
    <Text_2>WS BodayWash</Text_2>
    <Company>1</Company>
  </Item>
  <Item>
    <Text_1>6</Text_1>
    <Text_2>WS BodayWash</Text_2>
    <Company>0123</Company>
  </Item>
  <Item>
    <Text_1>5</Text_1>
    <Text_2>Shampoo</Text_2>
    <Company>2</Company>
  </Item>
  <Item>
    <Text_1>5</Text_1>
    <Text_2>Shampoo</Text_2>
    <Company>0123</Company>
  </Item>
</DocumentElement>

我正在尝试根据条件删除所有重复项

  1. 如果 Text_1 和 Company 相同。

  2. 如果第 1 点为真,则保留所有在 WS 标记中具有值的记录,并删除在 WS 标记中没有值的记录。

你能建议我做错什么吗

标签: xsltxslt-1.0

解决方案


<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:m="http://schemas.microsoft.com/dynamics/2011/01/documents/Message" 
xmlns:r="http://schemas.microsoft.com/dynamics/2008/01/documents/TRH_FinalQuery" 
exclude-result-prefixes="m r">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />

<xsl:key name="myKey" match="r:TRH_UnionView" use="concat(r:Text_1, '|', r:Company)" />

<!-- Simplify things by not having an identity. Using this approach, you will not have to suppress 
     any elements.
-->
<xsl:template match="node()">
  <xsl:apply-templates select="node()"/>
</xsl:template>

<!-- Start at the root. -->
<xsl:template match="/">
  <DocumentElement>
    <xsl:apply-templates select="node()" />
  </DocumentElement>  
</xsl:template>
  
<xsl:template match="r:TRH_UnionView">
  <xsl:choose>
    <!-- Handle the duplicates with no value in the WS tag. -->
    <xsl:when test="count(key('myKey',concat(r:Text_1, '|', r:Company))) &gt; 1 and 
                    count((key('myKey',concat(r:Text_1, '|', r:Company)))[r:WS!='']) = 0">
      <!-- Is this the first of the duplicates?  -->
      <xsl:if test="generate-id(.) = generate-id(key('myKey',concat(r:Text_1, '|', r:Company))[1])">
       <Item>
          <Text_1>
            <xsl:value-of select="r:Text_1"/>
          </Text_1>
          <Text_2>
            <xsl:value-of select="r:Text_2"/>            
          </Text_2>
          <Company>
            <xsl:value-of select="r:Company"/>
          </Company>
        </Item>
        <Item>
          <Text_1>
            <xsl:value-of select="r:Text_1"/>
          </Text_1>
          <Text_2>
            <xsl:value-of select="r:Text_2"/>            
          </Text_2>
          <Company>0123</Company>
        </Item>
      </xsl:if>
     </xsl:when>
    <!-- Handle the duplicates with value at least one value in the WS tag. -->
    <xsl:when test="count(key('myKey',concat(r:Text_1, '|', r:Company))) &gt; 1">
      <xsl:if test="r:WS!=''">
        <Item>
          <Text_1>
            <xsl:value-of select="r:WS" />
          </Text_1>
          <Text_2>WS BodayWash</Text_2>
          <Company>
            <xsl:value-of select="r:Text_1" />
          </Company>
        </Item>
        <Item>
          <Text_1>
            <xsl:value-of select="r:WS" />
          </Text_1>
          <Text_2>WS BodayWash</Text_2>
          <Company>0123</Company>
        </Item>
      </xsl:if>
    </xsl:when>
    <xsl:otherwise>
      <Item>
        <Text_1>
          <xsl:value-of select="r:Text_1"/>
        </Text_1>
        <Text_2>
          <xsl:value-of select="r:Text_2"/>            
        </Text_2>
        <Company>
          <xsl:value-of select="r:Company"/>
        </Company>
      </Item>
      <Item>
        <Text_1>
          <xsl:value-of select="r:Text_1"/>
        </Text_1>
        <Text_2>
          <xsl:value-of select="r:Text_2"/>            
        </Text_2>
        <Company>0123</Company>
      </Item>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

</xsl:stylesheet>

推荐阅读