XSLT Removing duplicates

前端 未结 4 1574
Happy的楠姐
Happy的楠姐 2020-12-17 04:54

I have an xml datasource which looks like this:


  
    
      

        
相关标签:
4条回答
  • 2020-12-17 05:35

    You haven't shown your desired output. But in XSLT 2.0, you could do something like this:

    <xsl:template match="Rows">
      <xsl:for-each-group select="Row" group-by="@region">
        <region name="{current-grouping-key()}">
          <xsl:for-each-group select="current-group()" group-by="@dept">
            <dept name="{current-grouping-key()}">
              <xsl:for-each select="current-group()">
                <state name="{@state}"/>
              </xsl:for-each>
            </dept>
          </xsl:for-each-group>
        </region>
      </xsl:for-each>
    </xsl:template>
    
    0 讨论(0)
  • 2020-12-17 05:40

    The following stylesheet shows a general approach to grouping at multiple levels:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:key name="byRegion" match="Row" use="@region" />
        <xsl:key name="byRegionState" 
                 match="Row" use="concat(@region, '|', @state)" />
        <xsl:key name="byRegionStateDept" 
                 match="Row" use="concat(@region, '|', @state, '|', @dept)" />
        <xsl:template 
             match="Row[generate-id() = generate-id(key('byRegion', @region)[1])]">
            <region name="{@region}">
                <xsl:apply-templates
                    select="key('byRegion', @region)
                             [generate-id() =
                              generate-id(key('byRegionState',
                                          concat(@region, '|', @state))[1])]"
                    mode="states" />
            </region>
        </xsl:template>
        <xsl:template match="Row" mode="states">
            <state name="{@state}">
                <xsl:apply-templates
                    select="key('byRegionState', concat(@region, '|', @state))
                             [generate-id() =
                              generate-id(key('byRegionStateDept',
                                    concat(@region, '|', @state, '|', @dept))[1])]"
                    mode="dept" />
            </state>
        </xsl:template>
        <xsl:template match="Row" mode="dept">
            <dept><xsl:value-of select="@dept" /></dept>
        </xsl:template>
    </xsl:stylesheet>
    

    It produces the following output on your input:

    <region name="East">
        <state name="NY">
            <dept>HR</dept>
            <dept>SD</dept>
            <dept>MM</dept>
        </state>
        <state name="NJ">
            <dept>HR</dept>
            <dept>SD</dept>
        </state>
    </region>
    <region name="West">
        <state name="CO">
            <dept>SD</dept>
            <dept>MM</dept>
        </state>
    </region>
    
    0 讨论(0)
  • 2020-12-17 05:42

    For XSLT 1.0 you can use the "Muenchian Method".

    You would create a key to index the Row elements by a combination of @region and @dept values.

    Then you would get the first occurrence of that region/department combination (that has the wanted region ($DeptQS)) and output the department (dept).

    Here's an example stylesheet outputting <test> elements to show the context:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output indent="yes" method="xml" omit-xml-declaration="yes"/>
      <xsl:strip-space elements="*"/>
    
      <xsl:key name="kDept" match="Department/Rows/Row" use="concat(@region,'|',@dept)"/>
      <xsl:param name="DeptQS">East</xsl:param>
    
      <xsl:template match="/*">
        <xsl:for-each select="Department/Rows/Row[count(.|key('kDept',
          concat($DeptQS,'|',@dept))[1])=1]">
          <test>Current dept: <xsl:value-of select="@dept"/></test>
        </xsl:for-each>
      </xsl:template>
    
    </xsl:stylesheet>
    

    Here's the output using your input XML:

    <test>Current dept: HR</test>
    <test>Current dept: SD</test>
    <test>Current dept: MM</test>
    
    0 讨论(0)
  • 2020-12-17 05:42

    how can I write out the department for the region only once?

    This stylesheet:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:param name="pRegion" select="'East'"/>
        <xsl:key name="kRowByDept-Region" match="Row"
                 use="concat(@dept,'++',@region)"/>
        <xsl:template match="Rows">
            <xsl:apply-templates select="Row[generate-id()
                                              = generate-id(
                                                   key('kRowByDept-Region',
                                                       concat(@dept,'++',$pRegion)
                                                   )[1]
                                                )
                                         ]"/>
        </xsl:template>
        <xsl:template match="Row">
            <xsl:value-of select="concat(@dept,'&#xA;')"/>
        </xsl:template>
    </xsl:stylesheet>
    

    Output:

    HR
    SD
    MM
    
    0 讨论(0)
提交回复
热议问题