xsl-list
[Top] [All Lists]

Re: [xsl] Grouping problem

2010-04-08 13:27:28
Joel Dubien wrote:

Desired Output:
<item>
    <master_affiliate_id>68800</master_affiliate_id>
    <queries_by_period>75,120,0,0</queries_by_period>
    <subitems>
        <item>
            <affiliate_id>68801</affiliate_id>
            <queries_by_period>75,120,0,0</queries_by_period>
        </item>
    </subitems>
</item>
<item>
    <master_affiliate_id>69767</master_affiliate_id>
    <queries_by_period>75,120,0,0</queries_by_period>
    <subitems>
        <item>
            <affiliate_id>69775</affiliate_id>
            <queries_by_period>75,120,0,0</queries_by_period>
        </item>
    </subitems>
</item>

Here is an XSLT 1.0 stylesheet that produces the described output:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
  version="1.0">

  <xsl:output indent="yes"/>

  <xsl:param name="plist" select="'test2010040802.xml'"/>
<xsl:variable name="periods" select="document($plist)/period_list/period"/>

  <xsl:variable name="main-root" select="/"/>

  <xsl:key name="k1" match="master_affiliate" use="master_affiliate_id"/>

<xsl:key name="k2" match="master_affiliate/summary" use="concat(../master_affiliate_id, '|', period)"/>

  <xsl:key name="k3" match="affiliates/affiliate" use="affiliate_id"/>

<xsl:key name="k4" match="affiliates/affiliate" use="concat(affiliate_id, '|', period)"/>

  <xsl:template match="/">
<xsl:for-each select="descendant::master_affiliate[generate-id() = generate-id(key('k1', master_affiliate_id)[1])]">
      <xsl:variable name="cgk" select="master_affiliate_id"/>
      <item>
        <xsl:copy-of select="master_affiliate_id"/>
        <queries_by_period>
          <xsl:for-each select="$periods">
            <xsl:variable name="period" select="."/>
            <xsl:for-each select="$main-root">
<xsl:variable name="s" select="key('k2', concat($cgk, '|', $period))"/>
              <xsl:choose>
                <xsl:when test="$s">
                  <xsl:value-of select="$s/queries"/>
                </xsl:when>
                <xsl:otherwise>0</xsl:otherwise>
              </xsl:choose>
            </xsl:for-each>
<xsl:if test="position() != last()"><xsl:text>,</xsl:text></xsl:if>
          </xsl:for-each>
        </queries_by_period>
        <subitems>
<xsl:for-each select="key('k1', master_affiliate_id)/affiliates/affiliate[generate-id() = generate-id(key('k3', affiliate_id)[1])]">
            <item>
              <xsl:copy-of select="affiliate_id"/>
              <xsl:variable name="cgk1" select="affiliate_id"/>
              <queries_by_period>
                <xsl:for-each select="$periods">
                  <xsl:variable name="period" select="."/>
                  <xsl:for-each select="$main-root">
<xsl:variable name="s" select="key('k4', concat($cgk1, '|', $period))"/>
                    <xsl:choose>
                      <xsl:when test="$s">
                        <xsl:value-of select="$s/queries"/>
                      </xsl:when>
                      <xsl:otherwise>0</xsl:otherwise>
                    </xsl:choose>
                  </xsl:for-each>
<xsl:if test="position() != last()"><xsl:text>,</xsl:text></xsl:if>
                </xsl:for-each>
              </queries_by_period>
            </item>
          </xsl:for-each>
        </subitems>
      </item>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

I am not quite sure however it will work for more complex input documents as I am not sure the same affiliate could occur under different master_affiliate elements. In that case the key 'k4' would need to include the master affiliate id as well.


--

        Martin Honnen
        http://msmvps.com/blogs/martin_honnen/

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

<Prev in Thread] Current Thread [Next in Thread>