Find maximum value of all child elements and get its parent element in XSLT

后端 未结 3 1235
一生所求
一生所求 2021-01-06 05:51

Using the below XML, I need to figure out which person worked more hours in each site. For instance in the below XML, person 1 worked 8 hours in site 1 but person 2 worked o

相关标签:
3条回答
  • 2021-01-06 06:20

    An XSLT 1.0 solution. This stylesheet:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:key name="BySite" match="WorkSite" use="@Site"/>
     <xsl:template match="root">
      <root>
       <xsl:for-each select="/*/WorkSite[count(.|key('BySite',@Site)[1])=1]">
        <WorkSite Person="{key('BySite',@Site)
                           [not(key('BySite',@Site)/Hours 
                                > Hours)]/@Person}"
                  Site="{@Site}" />
       </xsl:for-each>
      </root>
     </xsl:template>
    </xsl:stylesheet>
    

    Output:

    <root>
     <WorkSite Person="P1" Site="S1" />
     <WorkSite Person="P2" Site="S2" />
     <WorkSite Person="P1" Site="S3" />
    </root>
    
    0 讨论(0)
  • 2021-01-06 06:27
    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
       <xsl:template match="/">
          <root>
             <xsl:for-each-group select="*/WorkSite" group-by="@Site">
                <WorkSite Person="{(current-group()[Hours = max(current-group()/Hours)])[1]/@Person}" Site="{current-grouping-key()}" />
             </xsl:for-each-group>
          </root>
       </xsl:template>
    
    </xsl:stylesheet>
    
    0 讨论(0)
  • 2021-01-06 06:41

    This XSLT 1.0 transformation:

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <xsl:key name="kSiteByName" match="@Site" use="."/>
    
     <xsl:key name="kWorksiteBySite"
       match="WorkSite" use="@Site"/>
    
     <xsl:variable name="vSites" select=
      "/*/*/@Site[generate-id()
                 =
                  generate-id(key('kSiteByName',.)[1])
                  ]"
      />
    
     <xsl:template match="/">
      <root>
        <xsl:for-each select="$vSites">
          <xsl:for-each select="key('kWorksiteBySite', .)">
            <xsl:sort select="Hours" data-type="number"
             order="descending"/>
            <xsl:if test="position()=1">
             <xsl:copy>
               <xsl:copy-of select="@*"/>
             </xsl:copy>
            </xsl:if>
          </xsl:for-each>
        </xsl:for-each>
      </root>
     </xsl:template>
    </xsl:stylesheet>
    

    when applied on the provided XML document:

    <root>
        <WorkSite Person="P1" Site="S1">
            <Hours>8</Hours>
        </WorkSite>
        <WorkSite Person="P1" Site="S2">
            <Hours>2</Hours>
        </WorkSite>
        <WorkSite Person="P1" Site="S3">
            <Hours>9</Hours>
        </WorkSite>
        <WorkSite Person="P2" Site="S1">
            <Hours>6</Hours>
        </WorkSite>
        <WorkSite Person="P2" Site="S2">
            <Hours>10</Hours>
        </WorkSite>
        <WorkSite Person="P2" Site="S3">
            <Hours>2</Hours>
        </WorkSite>
    </root>
    

    produces the wanted, correct result:

    <root>
        <WorkSite Person="P1" Site="S1"/>
        <WorkSite Person="P2" Site="S2"/>
        <WorkSite Person="P1" Site="S3"/>
    </root>
    

    Do note:

    1. The use of the Muenchian method for grouping to find all different Site values.

    2. The way maximum is found by sorting in descending order and getting the first result from the sorted node-list.

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