Wrox Programmer Forums
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old February 18th, 2005, 03:14 PM
Friend of Wrox
 
Join Date: Oct 2003
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default SORT

Hi,

I would like to sort this xml document but I do not know how to do that. Basically, I use xslt to create a report but currently the html produced is not sorted. So I get something like this:

************
  ...
  ...
Age
  ...
  ...

But I would to sort it so that I would get

Age
  ...
  ...
************
  ...
  ...

and so on

Please not that the xml below is only an extract. The real xml has lots of:
<Reports>
   <Report>
      <Rows>
        <variable>
          <Name>
tags.

Since, I do not have control of the xml being produced I would like to find a way to sort it using xslt and would appreciate if someone could post some sample code.

Cheers,

Claudio

XML SAMPLE

<?xml version="1.0"?>
<Reports xmlns="x-schema:report.xdr">
    <User>
        <ReportID>1</ReportID>
        <FilterID>1</FilterID>
        <SurveyID>TGI2001</SurveyID>
    </User>
    <Report id="r1">
        <Name>Sample XML Report 3c</Name>
        <DataTypes>
            <DataType type="1">
                <Label>Weighted</Label>
            </DataType>
        </DataTypes>
        <Headers>
            <Title>
                <LeftText>Choices</LeftText>
                <LineIndex>1</LineIndex>
            </Title>
            <Title>
                <RightText>ReportML v1.0</RightText>
                <LineIndex>1</LineIndex>
            </Title>
            <Title>
                <CentreText>Sample XML Report 3c</CentreText>
                <LineIndex>2</LineIndex>
            </Title>
        </Headers>
        <Footers>
            <Title>
                <LeftText>Some comment about this table</LeftText>
                <LineIndex>1</LineIndex>
            </Title>
        </Footers>
        <Filters>
            <Variable id="1">
                <Name>************</Name>
                <Value id="1">
                    <Name>Adults</Name>
                    <Expr>DBSEXLAD</Expr>
                </Value>
            </Variable>
        </Filters>
        <Columns>
            <Variable id="0">
                <Value id="0">
                    <Name>Total</Name>
                </Value>
            </Variable>
            <Variable id="1">
                <Name>************</Name>
                <Value id="1">
                    <Name>Men</Name>
                    <Expr>DBSEXLME</Expr>
                </Value>
            </Variable>
        </Columns>
        <Rows>
            <Variable id="0">
                <Value id="0">
                    <Name>Total</Name>
                </Value>
            </Variable>
            <Variable id="1">
                <Name>************</Name>
                <Value id="1">
                    <Name>Women</Name>
                    <Expr>DBSEXLWO</Expr>
                </Value>
            </Variable>
                       <Variable id="1">
                <Name>Age</Name>
                <Value id="1">
                    <Name>Women</Name>
                    <Expr>DBSEXLWO</Expr>
                </Value>
            </Variable>

        </Rows>
        <Survey id="TGI2001">
            <Source>TGI full year 2001 survey</Source>
            <Copyright>BMRB International 2001</Copyright>
            <Cell type="1" filterid="1" colid="0" rowid="0">
                <DataValue>100</DataValue>
            </Cell>
            <Cell type="1" filterid="1" colid="1" rowid="0">
                <DataValue>50</DataValue>
            </Cell>
            <Cell type="1" filterid="1" colid="0" rowid="1">
                <DataValue>50</DataValue>
            </Cell>
            <Cell type="1" filterid="1" colid="1" rowid="1">
                <DataValue>0</DataValue>
            </Cell>
        </Survey>
    </Report>
</Reports>


 
Old February 20th, 2005, 10:39 AM
Friend of Wrox
 
Join Date: Oct 2003
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default

Hi,

I would appreciate if someone could answer my firt post. Is it possible to sort
the xml? I would like to sort by the <Name> tags child of <Variable> child of <Rows> but only when the <Variable> tag has a <Name> child:

This is the section of the xml I would like to sort:

<Rows>
            <Variable id="0">
                <Value id="0">
                    <Name>Total</Name>
                </Value>
            </Variable>
            <Variable id="1">
                <Name>************</Name>
                <Value id="1">
                    <Name>Women</Name>
                    <Expr>DBSEXLWO</Expr>
                </Value>
            </Variable>
            <Variable id="1">
                <Name>Age</Name>
                <Value id="1">
                    <Name>Women</Name>
                    <Expr>DBSEXLWO</Expr>
                </Value>
            </Variable>

        </Rows>

Cheers,

Claudio

 
Old February 20th, 2005, 11:54 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Yes, it's possible to sort the XML.

But I'm sorry, I can't tell from your description what you want the output to be, so I can't tell you how to achieve it.

Also, it's not clear why you're having difficulty: you haven't shown us your unsuccessful attempts. I assume you are aware that sorting in XSLT is done using the xsl:sort element.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old February 21st, 2005, 09:29 AM
Friend of Wrox
 
Join Date: Oct 2003
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default

Hi Michael,

Sorry for not being so clear about how the output should be. Basically, I want to sort by numbers <DataValue> element so that people can see the highest numbers first. Also, I have managed to sort by <Name> element but would like to use parameters so that users can decide what to sort by.

I have tried this approach and have hard coded some parameters at the top but it is not workin and I cannot figure out why
<xsl:sort select="$sortfield" order="ascending"/>


I am posting the whole xml and xslt below. It is all working fine except I can not sort by <DataType> element and cannot get the parameters to work.

All the work for the rows is done inside the <xsl:template name="RowsValue">.

Also, I tried this to sort by <DataValue> but since I need to match the Current Cell ID with the Current Column Id - Cell[@colid=$CurrentColID] I cannot have a xsl:sort element after a <xsl:variable> declaration but I need this to output right <DataValue>

<xsl:for-each select="//Report[@id=$ReportID]/Columns/Variable/Value">
<xsl:variable name="CurrentColID"><xsl:value-of select="@id"/></xsl:variable>







XSLT
========

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="html"/>


<xsl:param name="sortfield" select="Name" />
<xsl:param name="sortorder" select="ascending" />

<xsl:template match="Reports">

<html><head>
    <link rel="stylesheet" href="main.css"/>
    <title>Choices.NET Report</title>

    <body bgcolor="#FFFFFF" text="#000000" leftmargin="0" topmargin="0" bottommargin="0" rightmargin="0" class="Report">
        <xsl:call-template name="generateTable"/>
    </body>
</head></html>
</xsl:template>

<xsl:template name="generateTable">
    <table width="100%" border="0" cellpadding="1" cellspacing="0" bordercolor="black" bgcolor="white">
        <tr>
            <td><xsl:call-template name="titleTable"/></td>
        </tr>
        <tr>
            <td><xsl:call-template name="dynamicDataTable"/></td>
        </tr>
        <tr>
            <td><xsl:call-template name="footerTable"/></td>
        </tr>
        <tr>
            <td><xsl:call-template name="copyrightTable"/></td>
        </tr>
    </table>
</xsl:template>

<xsl:template name="titleTable">
    <xsl:variable name="ReportID"><xsl:value-of select="User/ReportID"/></xsl:variable>

    <table width="75%" border="0" align="center" class="TableHeaders">



        <tr align="center" valign="middle">
            <td width="25%" align="left" class="HeaderLeft">
                <xsl:choose>
                    <xsl:when test="Report[@id=$ReportID]/Headers/Title[LineIndex='1']/LeftText">
                        <xsl:value-of select="Report[@id=$ReportID]/Headers/Title[LineIndex='1']/LeftText"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
                    </xsl:otherwise>
                </xsl:choose>
            </td>

            <td width="50%" align="center" class="HeaderCentre" >
                <xsl:choose>
                    <xsl:when test="Report[@id=$ReportID]/Headers/Title[LineIndex='1']/CentreText">
                        <xsl:value-of select="Report[@id=$ReportID]/Headers/Title[LineIndex='1']/CentreText"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
                    </xsl:otherwise>
                </xsl:choose>
            </td>

            <td width="25%" align="right" class="HeaderRight">
                <xsl:choose>
                    <xsl:when test="Report[@id=$ReportID]/Headers/Title[LineIndex='1']/RightText">
                        <xsl:value-of select="Report[@id=$ReportID]/Headers/Title[LineIndex='1']/RightText" />
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
                    </xsl:otherwise>
                </xsl:choose>
            </td>
        </tr>



        <tr>
            <td width="25%" align="left" class="HeaderLeft">
                <xsl:choose>
                    <xsl:when test="Report[@id=$ReportID]/Headers/Title[LineIndex='2']/LeftText">
                        <xsl:value-of select="Report[@id=$ReportID]/Headers/Title[LineIndex='2']/LeftText"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
                    </xsl:otherwise>
                </xsl:choose>
            </td>

            <td width="50%" align="center" class="HeaderCentre">
                <xsl:choose>
                    <xsl:when test="Report[@id=$ReportID]/Headers/Title[LineIndex='2']/CentreText">
                        <xsl:value-of select="Report[@id=$ReportID]/Headers/Title[LineIndex='2']/CentreText"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
                    </xsl:otherwise>
                </xsl:choose>
            </td>

            <td width="25%" align="right" class="HeaderRight">
                <xsl:choose>
                    <xsl:when test="Report[@id=$ReportID]/Headers/Title[LineIndex='2']/RightText">
                        <xsl:value-of select="Report[@id=$ReportID]/Headers/Title[LineIndex='2']/RightText"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
                    </xsl:otherwise>
                </xsl:choose>
            </td>
        </tr>



        <tr>
            <td width="25%" align="left" class="HeaderLeft">
                <xsl:choose>
                    <xsl:when test="Report[@id=$ReportID]/Headers/Title[LineIndex='3']/LeftText">
                        <xsl:value-of select="Report[@id=$ReportID]/Headers/Title[LineIndex='3']/LeftText"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
                    </xsl:otherwise>
                </xsl:choose>
            </td>

            <td width="50%" align="center" class="HeaderCentre">
                <xsl:choose>
                    <xsl:when test="Report[@id=$ReportID]/Headers/Title[LineIndex='3']/CentreText">
                        <xsl:value-of select="Report[@id=$ReportID]/Headers/Title[LineIndex='3']/CentreText"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
                    </xsl:otherwise>
                </xsl:choose>
            </td>

            <td width="25%" align="right" class="HeaderRight">
                <xsl:choose>
                    <xsl:when test="Report[@id=$ReportID]/Headers/Title[LineIndex='3']/RightText">
                        <xsl:value-of select="Report[@id=$ReportID]/Headers/Title[LineIndex='3']/RightText"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
                    </xsl:otherwise>
                </xsl:choose>
            </td>
        </tr>
    </table>
</xsl:template>



<xsl:template name="dynamicDataTable">
    <table border="1" align="center" class="TableData">
        <xsl:call-template name="Filter"/>
        <xsl:call-template name="ColumnsValue"/>
        <xsl:call-template name="RowsValue"/>
    </table>
</xsl:template>


<xsl:template name="Filter">
    <xsl:variable name="ReportID"><xsl:value-of select="User/ReportID"/></xsl:variable>
    <xsl:variable name="FilterID"><xsl:value-of select="User/FilterID"/></xsl:variable>

    <tr bordercolor="#FFFFFF">
        <td class="FilterName">
            <xsl:attribute name="title"><xsl:value-of select="Report[@id=$ReportID]/Filters/Variable/Value[@id=$FilterID]/Expr"/></xsl:attribute>
                Filter: <xsl:value-of select="Report[@id=$ReportID]/Filters/Variable[Value[@id=$FilterID]]/Name"/>:
                       <xsl:value-of select="Report[@id=$ReportID]/Filters/Variable/Value[@id=$FilterID]/Name"/>
        </td>



        <xsl:for-each select="Report[@id=$ReportID]/Columns/Variable">
            <td align="right">
                <xsl:if test="Name">
                    <xsl:attribute name="class">ColumnVariableName</xsl:attribute>
                </xsl:if>
                <xsl:call-template name="getName"/>
            </td>
        </xsl:for-each>
    </tr>
</xsl:template>



<xsl:template name="getName">
    <xsl:choose>
        <xsl:when test="Name">
            <xsl:value-of select="Name"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template name="ColumnsValue">

        <xsl:variable name="ReportID"><xsl:value-of select="User/ReportID"/></xsl:variable>



    <tr bordercolor="#FFFFFF">
        <td>
            <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
        </td>

    <xsl:for-each select="Report[@id=$ReportID]/Columns/Variable/Value">
            <td width="150" align="right" class="ColumnValueName">
                <xsl:attribute name="title"><xsl:value-of select="Expr"/></xsl:attribute>
                <xsl:call-template name="getName"/>
            </td>
        </xsl:for-each>
    </tr>
</xsl:template>

<xsl:template name="RowsValue">
    <xsl:variable name="ReportID"><xsl:value-of select="User/ReportID"/></xsl:variable>
    <xsl:variable name="SurveyID"><xsl:value-of select="User/SurveyID"/></xsl:variable>



    <xsl:for-each select="Report[@id=$ReportID]/Rows/Variable">
        <xsl:sort select="$sortfield" order="ascending"/>

        <xsl:if test="Name">

            <tr>
               <td align="left" class="RowVariableName">
                <xsl:attribute name="colspan"><xsl:value-of select="count(//Report[@id=$ReportID]/Columns/Variable/Value)+1"/></xsl:attribute> <xsl:call-template name="getName"/>
               </td>
            </tr>
        </xsl:if>




        <xsl:for-each select="Value">
        <xsl:sort select="$sortfield" order="ascending"/>
            <xsl:variable name="CurrentRowID" select="@id"/>
                <tr bordercolor="#FFFFFF" align="right">
                    <td><xsl:value-of select="Name"/></td>

                    <xsl:for-each select="//Report[@id=$ReportID]/Columns/Variable/Value">

                        <xsl:variable name="CurrentColID"><xsl:value-of select="@id"/></xsl:variable>








                        <td>
<xsl:value-of select="//Report[@id=$ReportID]/Survey[@id=$SurveyID]/Cell[@colid=$CurrentColID and @rowid=$CurrentRowID]/DataValue"/>
                        </td>
                    </xsl:for-each>
                </tr>
        </xsl:for-each>
    </xsl:for-each>
</xsl:template>

<xsl:template name="footerTable">

    <xsl:variable name="ReportID"><xsl:value-of select="User/ReportID"/></xsl:variable>

    <table width="75%" border="0" align="center" class="Tablefooters">
        <tr>
            <td width="33%" align="left"><xsl:value-of select="Report[@id=$ReportID]/Footers/Title/LeftText"/></td>
            <td align="center">#xa0;</td>
            <td width="33%" align="right">#xa0;</td>
        </tr>
    </table>
</xsl:template>

<xsl:template name="copyrightTable">
    <xsl:variable name="ReportID"><xsl:value-of select="User/ReportID"/></xsl:variable>
    <xsl:variable name="SurveyID"><xsl:value-of select="User/SurveyID"/></xsl:variable>

    <table width="75%" border="0" align="center" class="Tablefooters">
        <tr>
            <td width="33%" align="left"><xsl:value-of select="Report[@id=$ReportID]/Survey[@id=$SurveyID]/Source"/></td>
            <td align="center">#xa0;</td>
            <td width="33%" align="right"><xsl:value-of select="Report[@id=$ReportID]/Survey[@id=$SurveyID]/Copyright"/></td>
        </tr>
    </table>
</xsl:template>

</xsl:stylesheet>




XML
=====

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="report.xsl"?>
<Reports>
    <User>
        <ReportID>r1</ReportID>
        <FilterID>1</FilterID>
        <SurveyID>gb01q2p,ENG</SurveyID>
    </User>
    <Report id="r1">
        <Name>Untitled</Name>
        <DataTypes>
            <DataType type="1">
                <Label>Weighted</Label>
            </DataType>
        </DataTypes>
        <Headers>
            <Title>
                <LeftText>Choices 3 Report</LeftText>
                <LineIndex>1</LineIndex>
            </Title>
            <Title>
                <CentreText>Sample Choices.NET XML Report</CentreText>
                <LineIndex>2</LineIndex>
            </Title>
        </Headers>
        <Footers>
            <Title>
                <LeftText>Footnotes go here!</LeftText>
                <LineIndex>1</LineIndex>
            </Title>
        </Footers>
        <Filters>
            <Variable id="1">
                <Name>Filters</Name>
                <Value id="0">
                    <Name>Total</Name>
                </Value>
            </Variable>
        </Filters>
        <Columns>
            <Variable id="1">
                <Name>Columns</Name>
                <Value id="0">
                    <Name>Total</Name>
                </Value>
            </Variable>
            <Variable id="2">
                <Name>Bottled Table Wine: Use</Name>
                <Value id="1">
                    <Name>All Users</Name>
                    <Expr>BWBTFAUS</Expr>
                </Value>
                <Value id="2">
                    <Name>Non Users</Name>
                    <Expr>BWBTFNUS</Expr>
                </Value>
                <Value id="3">
                    <Name>Solus Users</Name>
                    <Expr>BWBTFSUS</Expr>
                </Value>
            </Variable>
        </Columns>
        <Rows>
            <Variable id="1">
                <Name>Rows</Name>
                <Value id="0">
                    <Name>Total</Name>
                </Value>
            </Variable>
            <Variable id="2">
                <Name>************</Name>
                <Value id="1">
                    <Name>All Men</Name>
                    <Expr>DBSEXLME</Expr>
                </Value>
                <Value id="2">
                    <Name>All Women</Name>
                    <Expr>DBSEXLWO</Expr>
                </Value>
            </Variable>
            <Variable id="3">
                <Name>Age</Name>
                <Value id="3">
                    <Name>15-24</Name>
                    <Expr>DBAGE152</Expr>
                </Value>
                <Value id="4">
                    <Name>25-34</Name>
                    <Expr>DBAGE253</Expr>
                </Value>
                <Value id="5">
                    <Name>35-44</Name>
                    <Expr>DBAGE354</Expr>
                </Value>
                <Value id="6">
                    <Name>45-54</Name>
                    <Expr>DBAGE455</Expr>
                </Value>
                <Value id="7">
                    <Name>55-64</Name>
                    <Expr>DBAGE556</Expr>
                </Value>
                <Value id="8">
                    <Name>65+</Name>
                    <Expr>DBAGE65+</Expr>
                </Value>
            </Variable>
            <Variable id="4">
                <Name>Social Grade</Name>
                <Value id="9">
                    <Name>ABC1</Name>
                    <Expr>DBSGABC1</Expr>
                </Value>
                <Value id="10">
                    <Name>C2DE</Name>
                    <Expr>DBSGC2DE</Expr>
                </Value>
            </Variable>
            <Variable id="5">
                <Name>Working Status</Name>
                <Value id="11">
                    <Name>Full-time - 30+ Hrs Per Week</Name>
                    <Expr>DBWSWFT</Expr>
                </Value>
                <Value id="12">
                    <Name>Part-time</Name>
                    <Expr>DBWSWPT</Expr>
                </Value>
                <Value id="13">
                    <Name>Not Working</Name>
                    <Expr>DBWSNWKG</Expr>
                </Value>
            </Variable>
            <Variable id="6">
                <Name>Marital Status</Name>
                <Value id="14">
                    <Name>Single</Name>
                    <Expr>DBMSSING</Expr>
                </Value>
                <Value id="15">
                    <Name>Married/Living as Married</Name>
                    <Expr>DBMSMARR</Expr>
                </Value>
                <Value id="16">
                    <Name>Separated/Divorced/Widowed</Name>
                    <Expr>DBMSSDW</Expr>
                </Value>
            </Variable>
            <Variable id="7">
                <Name>Standard Region</Name>
                <Value id="17">
                    <Name>Scotland</Name>
                    <Expr>DGSRSCOT</Expr>
                </Value>
                <Value id="18">
                    <Name>North West</Name>
                    <Expr>DGSRNWES</Expr>
                </Value>
                <Value id="19">
                    <Name>North</Name>
                    <Expr>DGSRNORT</Expr>
                </Value>
                <Value id="20">
                    <Name>Yorkshire &amp; Humberside</Name>
                    <Expr>DGSRY&amp;HU</Expr>
                </Value>
                <Value id="21">
                    <Name>East Midlands</Name>
                    <Expr>DGSREMID</Expr>
                </Value>
                <Value id="22">
                    <Name>East Anglia</Name>
                    <Expr>DGSREANG</Expr>
                </Value>
                <Value id="23">
                    <Name>South East</Name>
                    <Expr>DGSRSEAS</Expr>
                </Value>
                <Value id="24">
                    <Name>Greater London</Name>
                    <Expr>DGSRGLON</Expr>
                </Value>
                <Value id="25">
                    <Name>South West</Name>
                    <Expr>DGSRSWES</Expr>
                </Value>
                <Value id="26">
                    <Name>Wales</Name>
                    <Expr>DGSRWALE</Expr>
                </Value>
                <Value id="27">
                    <Name>West Midlands</Name>
                    <Expr>DGSRWMID</Expr>
                </Value>
                <Value id="28">
                    <Name>South East/East Anglia</Name>
                    <Expr>DGSRSEEA</Expr>
                </Value>
                <Value id="29">
                    <Name>South West/Wales</Name>
                    <Expr>DGSRSWWA</Expr>
                </Value>
                <Value id="30">
                    <Name>East &amp; West Midlands</Name>
                    <Expr>DGSRE&amp;WI</Expr>
                </Value>
                <Value id="31">
                    <Name>Yorkshire &amp; Humberside/North</Name>
                    <Expr>DGSRY&amp;HN</Expr>
                </Value>
            </Variable>
        </Rows>
        <Survey id="gb01q2p,ENG">
            <Source>GB TGI 2001 Summer (April 2000 - March 2001) 28/08/01</Source>
            <Copyright>Copyright BMRB International 2001</Copyright>
            <Cell type="1" filterid="0" colid="0" rowid="0">
                <DataValue>46685</DataValue>
            </Cell>
            <Cell type="1" filterid="0" colid="0" rowid="1">
                <DataValue>22753</DataValue>
            </Cell>
            <Cell type="1" filterid="0" colid="0" rowid="2">
                <DataValue>23932</DataValue>
            </Cell>
            <Cell type="1" filterid="0" colid="0" rowid="3">
                <DataValue>6954.27</DataValue>
            </Cell>
            <Cell type="1" filterid="0" colid="0" rowid="4">
                <DataValue>8662.48</DataValue>
            </Cell>
            <Cell type="1" filterid="0" colid="0" rowid="5">
                <DataValue>8527.03</DataValue>
            </Cell>
            <Cell type="1" filterid="0" colid="0" rowid="6">
                <DataValue>7593.98</DataValue>
            </Cell>
            <Cell type="1" filterid="0" colid="0" rowid="7">
                <DataValue>5880.71</DataValue>
            </Cell>
            <Cell type="1" filterid="0" colid="0" rowid="8">
                <DataValue>9066.51</DataValue>
            </Cell>
            <Cell type="1" filterid="0" colid="0" rowid="9">
                <DataValue>23757.2</DataValue>
            </Cell>
            <Cell type="1" filterid="0" colid="0" rowid="10">
                <DataValue>22927.8</DataValue>
            </Cell>
            <Cell type="1" filterid="0" colid="0" rowid="11">
                <DataValue>19397.7</DataValue>
            </Cell>
            <Cell type="1" filterid="0" colid="0" rowid="12">
                <DataValue>5483.12</DataValue>
            </Cell>
            <Cell type="1" filterid="0" colid="0" rowid="13">
                <DataValue>21786.6</DataValue>
            </Cell>
            <Cell type="1" filterid="0" colid="0" rowid="14">
                <DataValue>10
 
Old February 21st, 2005, 10:23 AM
Authorized User
 
Join Date: Jul 2004
Posts: 53
Thanks: 0
Thanked 0 Times in 0 Posts
Default

The following line:

   <xsl:param name="sortfield" select="Name" />

is selecting a non-existant node (Name), use a string to represent the name of the required node:

   <xsl:param name="sortfield" select="'Name'" />

then the select becomes

   <xsl:sort select="*[name()=$sortfield]" ....

Regards
Bryan

 
Old February 21st, 2005, 10:31 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

In this:

<xsl:sort select="$sortfield" order="ascending"/>

the sort key has the same value for every record being sorted - whatever the value of variable $sortfield is at the start of the sort. It never makes sense to use a sort key that doesn't depend in some way on the context node.

Perhaps you're thinking that if the value of $sortfield is an expression, the expression will be evaluated once for each record. But the value of a variable can never be an expression - values are always integers, strings, booleans, or node-sets.

There's an extension in some products, e.g. Saxon, that allows you to write <xsl:sort select="dyn:evaluate($sortfield)"/>. In this case $sortfield holds a string which is interpreted as an XPath expression and is evaluated once for each record being sorted.

If your variable is always the name of a child element of the elements being sorted, and not some more complex expression, then you can use

<xsl:sort select="*[name()=$sortfield]"/>

P.S. I hope you understand better now why your original post got no replies. There was nothing in it that gave any clue as to where you were going wrong.




Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old February 21st, 2005, 05:54 PM
Friend of Wrox
 
Join Date: Oct 2003
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default

Hi Michael and Bryan,

Thanks ever so much for your reply.

What about to sort the <DataValue> element.

<Cell type="1" filterid="0" colid="6" rowid="13">
    <DataValue>3717.47</DataValue>
</Cell>

I cannot really figure out how to do that and would be very grateful if you could help me. The reason why this is so difficult is that I am having to go back up the tree to find the Columns/Variable/Value and then create a variable
<xsl:variable name="CurrentColID"><xsl:value-of select="@id"/></xsl:variable> to
compare like that and display the right <DataValue> number

<xsl:value-of select="//Report[@id=$ReportID]/Survey[@id=$SurveyID]/Cell[@colid=$CurrentColID and @rowid=$CurrentRowID]/DataValue"/>

Unfortunatelly, I cannot add the xsl:sort after declaring the variable because I get an error but at the same time I think I need the variable value to be able to sort by <DataValue>. What do you think?? Well, I am not good enough to work it out !!!

This is the bit of code I need help but I would appreciate if you could run the code provided and see what is happening.


<xsl:for-each select="//Report[@id=$ReportID]/Columns/Variable/Value">

                        <xsl:variable name="CurrentColID"><xsl:value-of select="@id"/></xsl:variable>








                        <td>
<xsl:value-of select="//Report[@id=$ReportID]/Survey[@id=$SurveyID]/Cell[@colid=$CurrentColID and @rowid=$CurrentRowID]/DataValue"/>
                        </td>
                    </xsl:for-each>

Cheers,

Claudio


 
Old February 21st, 2005, 06:18 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Firstly, this:

<xsl:variable name="CurrentColID"><xsl:value-of select="@id"/></xsl:variable>

is an incredibly long-winded and inefficient way of saying

<xsl:variable name="CurrentColID" select="@id"/>

Why create a whole new tree, when you just want a reference to a node?

Secondly, you're right that you can't use a variable before xsl:sort, but if this is your variable, you don't need to, because you can reference the value as current()/@id.

I don't think I have fully understood your source document structure, however, it looks to me like a candidate for a multi-phase transformation. Write one transformation that turns the data into a decent hierarchical XML representation that preperly reflects the semantics, and a second that goes from this to the output you want. The sorting will then be done in the second phase and you'll probably find that the sort key is readily accessible from the nodes you want to sort by means of a simple relative path expression.


Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old February 21st, 2005, 06:48 PM
Friend of Wrox
 
Join Date: Oct 2003
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default

Hi Michael,

This structure is based on the open standard OpenTabs. When I was devising the xml for the survey I decided to do something similar to the industry open standard so that other people or application could use my xslt as long as they used the same schema. Maybe I was wrong to do that.

When I write this variable <xsl:variable name="CurrentColID"><xsl:value-of select="@id"/></xsl:variable> I have to go back up the tree because my context is
/Rows/Variable/Value. (by the way thank a lot for the correction !!)

Once I get the right @id for the Column and right @id for the row, I can figure out the values for the rows of the table. Basically, I have columns and rows and I need to pick the values from the <Cell><DataValue> based on the attributes

<Cell type="1" filterid="0" colid="6" rowid="7">
                <DataValue>1030.64</DataValue>
            </Cell>
            <Cell type="1" filterid="0" colid="6" rowid="8">
                <DataValue>1730.92</DataValue>
            </Cell>
            <Cell type="1" filterid="0" colid="6" rowid="9">
                <DataValue>3443.39</DataValue>
            </Cell>

You said this might be a candidate for a multi-phase transformation. I am sorry but I do not know how to do it. Could you please provide a sample example??

Cheers,

Claudio








 
Old February 21st, 2005, 07:10 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

You might be working with a standard format, but it's one that captures no semantics - no-one looking at your data can tell what the cells and data values actually mean. That's one reason why it's so difficult for anyone to help you with your problem. If you can translate the data to something that talks about real semantic objects (employees, prices, and bicycles, not rows, cells and values) it will become much clearer what you are trying to do.

There also seems to be a cross-reference structure between different parts of your document that's very hard to follow; the data will be easier to manipulate if you bring related data together in a single hierarchy.

All complex transformations should be split up into a pipeline of simpler transformations - it's an essential design technique that is far too often neglected. There are two basic techniques you can use: several independent transformations coordinated via some application that invokes them in sequence (JAXP is well suited to this), or several phases executing within a single stylesheet. The general pattern is:

<xsl:variable name="temp1">
  <xsl:apply-templates select="/" mode="phase1"/>
</xsl:variable>

<xsl:template match="/">
  <xsl:apply-templates select="exslt:node-set($temp1)" mode="phase2"/>
</xsl:template>



Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference





Similar Threads
Thread Thread Starter Forum Replies Last Post
Dynamic sort order or sort datatype kapy_kal XSLT 2 September 18th, 2007 02:10 PM
how to sort cross tab.sort based on row total joxa83 Crystal Reports 7 March 2nd, 2006 09:12 AM
Sort @* sheila XSLT 2 July 17th, 2005 04:01 PM
Unable to sort using xsl sort command sly_jimmy_boy XSLT 3 June 17th, 2005 05:15 AM
sort by question elladi Classic ASP Databases 1 March 29th, 2005 11:12 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.