Re: [xsl] How to compare values between two different looping tags

Subject: Re: [xsl] How to compare values between two different looping tags
From: "Marrow" <marrow@xxxxxxxxxxxxxx>
Date: Fri, 26 Jul 2002 02:29:03 +0100
Hi,

Making some assumptions on how you want to process for the sample output:-
1) the element names (C,D & E etc.) are not predictable - but only those
elements that contain non-whitespace text are to be included in the table;
2) that the column names (element names) are to be sorted alphabetically
left-to-right;
3) that only distinct values for each column are to be shown - and these values
are to be sorted numerically ascending;
4) a html table is required (if you need text or xml output it shouldn't be too
much of a problem to modify the code)

NB.  If assumption #1 above is incorrect then some other criteria will be
required in the code below - by replacing occurences of the expression
'normalize-space(text())' with the desired criteria.

Something like?...

== XSL ===================================
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
<xsl:output method="html" indent="yes"/>
<!-- set-up keys for finding distinct names and distinct values within names -->
<xsl:key name="kNamedValues" match="*[normalize-space(text())]" use="name()"/>
<xsl:key name="kDistinctNamedValues" match="*[normalize-space(text())]"
use="concat(name(),'|',.)"/>
<!-- find the distinct columns -->
<xsl:variable name="vColumns" select="//*[normalize-space(text())][generate-id()
= generate-id(key('kNamedValues',name()))]"/>
<xsl:template match="/">
  <!-- find the maximum number of rows -->
  <xsl:variable name="vMaxRows">
    <xsl:for-each select="$vColumns">
      <xsl:sort select="count(key('kNamedValues',name())[generate-id() =
generate-id(key('kDistinctNamedValues',concat(name(),'|',.)))])"
data-type="number" order="descending"/>
      <xsl:if test="position() = 1">
        <xsl:value-of select="count(key('kNamedValues',name())[generate-id() =
generate-id(key('kDistinctNamedValues',concat(name(),'|',.)))])"/>
      </xsl:if>
    </xsl:for-each>
  </xsl:variable>
  <html>
    <body>
      <table border="1">
        <!-- header row -->
        <tr>
          <xsl:apply-templates select="$vColumns" mode="header-columns">
            <xsl:sort select="name()"/>
          </xsl:apply-templates>
        </tr>
        <!-- dummy apply through all nodes - to get up to max rows -->
        <xsl:apply-templates select="(//*)[position() &lt;= $vMaxRows]"
mode="rows"/>
      </table>
    </body>
  </html>
</xsl:template>

<xsl:template match="*" mode="header-columns">
  <th>
    <xsl:value-of select="name()"/>
  </th>
</xsl:template>

<xsl:template match="*" mode="rows">
  <tr>
    <xsl:apply-templates select="$vColumns" mode="data-cells">
      <xsl:sort select="name()"/>
      <xsl:with-param name="rel-posn" select="position()"/>
    </xsl:apply-templates>
  </tr>
</xsl:template>

<xsl:template match="*" mode="data-cells">
  <xsl:param name="rel-posn"/>
  <!-- get the distinct values for this named element -->
  <xsl:variable name="distinct-values"
select="key('kNamedValues',name())[generate-id() =
generate-id(key('kDistinctNamedValues',concat(name(),'|',.)))]"/>
  <!-- find the data for the relative position of these sorted distinct
values -->
  <xsl:variable name="this-item">
    <xsl:for-each select="$distinct-values">
      <xsl:sort data-type="number"/>
      <xsl:if test="position() = $rel-posn">
        <xsl:value-of select="."/>
      </xsl:if>
    </xsl:for-each>
  </xsl:variable>
  <!-- ouput the column -->
  <td align="right">
    <!-- decide if data cell exists to be displayed -->
    <xsl:choose>
      <xsl:when test="normalize-space($this-item)">
        <xsl:value-of select="$this-item"/>
      </xsl:when>
      <xsl:otherwise>
        <!-- blank cell -->
        <xsl:text>n/a</xsl:text>
      </xsl:otherwise>
    </xsl:choose>
  </td>
</xsl:template>
</xsl:stylesheet>
== end of XSL ==============================

Another alternative would be to use RTFs (Result Tree Fragments) to do some
pre-processing on the data.

Hope this helps
Marrow
http://www.marrowsoft.com - home of Xselerator (XSLT IDE and debugger)
http://www.topxml.com/Xselerator



-----Original Message-----
From: murli bk <bkmurali@xxxxxxxxxxx>
To: XSL-List@xxxxxxxxxxxxxxxxxxxxxx <XSL-List@xxxxxxxxxxxxxxxxxxxxxx>
Date: 25 July 2002 23:33
Subject: [xsl] How to compare values between two different looping tags


>Hi,
>I have an xml file like below.
>
><G>
>  <X>
>     <A>
>        <C>111</C>
>        <D>222</D>
>     </A>
>     <A>
>        <C>232</C>
>        <D>3232</D>
>     </A>
>  </X>
>
>  <Y>
>     <B>
>        <C>232</C>
>        <E>777</E>
>     </B>
>     <B>
>        <C>111</C>
>        <E>000</E>
>     </B>
>     <B>
>        <C>232</C>
>        <E>777</E>
>     </B>
>  </Y>
></G>
>
>How do you write an xsl to get a text output like below?
>
>C        D         E
>=======================
>111      222       000
>
>232     3232       777
>
>
>Thanks in advance,
>Murali.



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread