XSLT 可同时分组并删除重复项

问题描述 投票:0回答:2

下面是我的输入 XML。我想根据用户名对下面的 XML 进行分组,并删除 HierarchyLocation 中的任何重复项

下面是我输入的 XML

<data>
  <UploadUser>
    <User>
      <EmailAddress>test1.com</EmailAddress>
      <Username>User1</Username>
      <Replace>True</Replace>
    </User>
    <HierarchyLocations>
      <Hierarchy>Hierarchy</Hierarchy>
      <UserGroup>UserGroup1</UserGroup>
      <Location>43737</Location>
    </HierarchyLocations>
  </UploadUser>
  <UploadUser>
    <User>
      <EmailAddress>test2.com</EmailAddress>
      <Username>User2</Username>
      <Replace>True</Replace>
    </User>
    <HierarchyLocations>
      <Hierarchy>Hierarchy</Hierarchy>
      <UserGroup>UserGroup2</UserGroup>
      <Location>43737</Location>
    </HierarchyLocations>
  </UploadUser>
  <UploadUser>
    <User>
      <EmailAddress>test2.com</EmailAddress>
      <Username>User2</Username>
      <Replace>True</Replace>
    </User>
    <HierarchyLocations>
      <Hierarchy>Hierarchy</Hierarchy>
      <UserGroup>UserGroup2</UserGroup>
      <Location>43737</Location>
    </HierarchyLocations>
  </UploadUser>
    <UploadUser>
    <User>
      <EmailAddress>test2.com</EmailAddress>
      <Username>User2</Username>
      <Replace>True</Replace>
    </User>
    <HierarchyLocations>
      <Hierarchy>Hierarchy</Hierarchy>
      <UserGroup>UserGroup3</UserGroup>
      <Location>5230</Location>
    </HierarchyLocations>
  </UploadUser>
  </data>

以下是我的预期输出

<data>
  <UploadUser>
    <User>
      <EmailAddress>test1.com</EmailAddress>
      <Username>User1</Username>
      <Hierarchies>
        <Replace>True</Replace>
        <HierarchyLocations>
          <Hierarchy>Hierarchy</Hierarchy>
          <UserGroup>UserGroup1</UserGroup>
          <Location>43737</Location>
        </HierarchyLocations>
      </Hierarchies>
    </User>
    <User>
      <EmailAddress>test2.com</EmailAddress>
      <Username>User2</Username>
      <Hierarchies>
        <Replace>True</Replace>
        <HierarchyLocations>
          <Hierarchy>Hierarchy</Hierarchy>
          <UserGroup>UserGroup2</UserGroup>
          <Location>43737</Location>
        </HierarchyLocations>
        <HierarchyLocations>
          <Hierarchy>Hierarchy</Hierarchy>
          <UserGroup>UserGroup3</UserGroup>
          <Location>5230</Location>
        </HierarchyLocations>
      </Hierarchies>
    </User>
  </UploadUser>
</data>

我尝试了下面的 XSLT,但无法删除重复的 HierarchyLocations。

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="data">
    <xsl:copy>
        <UploadUser>
        <xsl:for-each-group select="UploadUser" group-by="User/Username">
            <User>
                <xsl:apply-templates select="current-group()[1]/User/EmailAddress" />
                <xsl:apply-templates select="current-group()[1]/User/Username" />
                <Hierarchies>
                <xsl:apply-templates select="current-group()[1]/User/Replace" />   
                    <xsl:for-each select="current-group()">
                        <xsl:apply-templates select="HierarchyLocations[not(Location=preceding-sibling::HierarchyLocations/Location)]" />
                    </xsl:for-each>
                </Hierarchies>
            </User>
        </xsl:for-each-group>
        </UploadUser>
    </xsl:copy>
</xsl:template>

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

使用上述 XSLT 输出。 层次结构位置与用户名“user2”重复,我需要删除比较所有 3 个字段(层次结构、用户组和位置)。我尝试不使用“preceding-sibling”来复制它,但仍然被复制了。

<data>
  <UploadUser>
    <User>
      <EmailAddress>test1.com</EmailAddress>
      <Username>User1</Username>
      <Hierarchies>
        <Replace>True</Replace>
        <HierarchyLocations>
          <Hierarchy>Hierarchy</Hierarchy>
          <UserGroup>UserGroup1</UserGroup>
          <Location>43737</Location>
        </HierarchyLocations>
      </Hierarchies>
    </User>
    <User>
      <EmailAddress>test2.com</EmailAddress>
      <Username>User2</Username>
      <Hierarchies>
        <Replace>True</Replace>
        <HierarchyLocations>
          <Hierarchy>Hierarchy</Hierarchy>
          <UserGroup>UserGroup2</UserGroup>
          <Location>43737</Location>
        </HierarchyLocations>
        <HierarchyLocations>
          <Hierarchy>Hierarchy</Hierarchy>
          <UserGroup>UserGroup2</UserGroup>
          <Location>43737</Location>
        </HierarchyLocations>
        <HierarchyLocations>
          <Hierarchy>Hierarchy</Hierarchy>
          <UserGroup>UserGroup3</UserGroup>
          <Location>5230</Location>
        </HierarchyLocations>
      </Hierarchies>
    </User>
  </UploadUser>
</data>
xslt xslt-1.0 xslt-2.0 xslt-grouping
2个回答
0
投票

只需在当前组上再进行一次分组即可:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="data">
    <xsl:copy>
        <UploadUser>
            <xsl:for-each-group select="UploadUser" group-by="User/Username">
                <User>
                    <xsl:copy-of select="User/(EmailAddress|Username)"/>
                    <Hierarchies>
                        <xsl:copy-of select="User/Replace"/>
                        <xsl:for-each-group select="current-group()/HierarchyLocations" group-by="string-join((Hierarchy, UserGroup, Location), '|')">
                            <xsl:copy-of select="."/>
                        </xsl:for-each-group>
                </Hierarchies>
            </User>
        </xsl:for-each-group>
        </UploadUser>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

请注意,在

xsl:for-each-group
中,组的第一项是上下文项 - 因此您可以摆脱那些尴尬的
current-group()[1]/something
表达式。


0
投票

这是 xslt,其中前一个同级部分的部分被重写。您位于当前组内,因此您可以迭代并使用索引来引用先前的迭代。

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="data">
    <xsl:copy>
        <UploadUser>
        <xsl:for-each-group select="UploadUser" group-by="User/Username">
            <User>
                <xsl:apply-templates select="current-group()[1]/User/EmailAddress" />
                <xsl:apply-templates select="current-group()[1]/User/Username" />
                <Hierarchies>
                <xsl:apply-templates select="current-group()[1]/User/Replace" />   
                    <xsl:variable name="sequence" select="current-group()"/>
                    <xsl:for-each select="1 to count($sequence)">
                        <xsl:variable name="position" select="."/>
                        <xsl:apply-templates select="$sequence[$position]/HierarchyLocations[not(Location=$sequence[$position -1]/HierarchyLocations/Location)]" />
                    </xsl:for-each>
                </Hierarchies>
            </User>
        </xsl:for-each-group>
        </UploadUser>
    </xsl:copy>
</xsl:template>

<xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()" />
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>
© www.soinside.com 2019 - 2024. All rights reserved.