Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
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 January 24th, 2007, 01:13 PM
Friend of Wrox
 
Join Date: Oct 2003
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default SLOW TRANSFORAMTION

Hi,

Note: I use xslt 1.0 and msxml

I have read the article on http://www.jenitennison.com/xslt/grouping regarding grouping and also Michael Kay's XSLT Programmer's Reference book 1.0 to find out how to use this technique to speed up my transformation.

However, I am still not sure how to apply this technique to my xml.
The xml below is just an extract of my real xml. In this sample I only add the columns section but the same model applies to the rows as well.

My xslt (please see below) works fine but unfortunately with a large xml it can be very slow.

I would really appreciate if you could send me some sample code based on my xml or change the xslt pasted below.

The measures node on my xml represent the dimension of my table.

Cheers

CPall

XML
===

<?xml version="1.0"?>
<Reports xmlns="">
  <Report>
    <Measures>
      <Measure idx="1" heading="Total Pages"/>
      <Measure idx="2" heading="Cost"/>
    </Measures>
    <Columns>
      <ColGrp heading="Year">
        <Col heading="2003"/>
        <Col heading="2004"/>
      </ColGrp>
    </Columns>
    <Rows>
      <RowGrp heading="Journal Group Name">
        <Row heading="Gastroenterology">
          <Cell/>
          <Cell>
            <Msr idx="1" val="42.00"/>
            <Msr idx="2" val="64230"/>
          </Cell>
        </Row>
        <Row heading="Other Specialty">
          <Cell/>
          <Cell>
            <Msr idx="1" val="36.00"/>
            <Msr idx="2" val="35820"/>
          </Cell>
        </Row>
        <Row heading="Pharmacy">
          <Cell>
            <Msr idx="1" val="14.20"/>
            <Msr idx="2" val="128030"/>
          </Cell>
          <Cell/>
        </Row>
      </RowGrp>
      <RowGrp heading="">
        <Row heading="Totals">
          <Cell>
            <Msr idx="1" val="14.20"/>
            <Msr idx="2" val="128030.00"/>
          </Cell>
          <Cell>
            <Msr idx="1" val="78.00"/>
            <Msr idx="2" val="100050.00"/>
          </Cell>
        </Row>
      </RowGrp>
    </Rows>
  </Report>
</Reports>


XSLT
====
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" version="1.0" encoding="iso-8859-1" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:param name="axisHeads" select="'false'" />

  <xsl:variable name="msrs">
    <xsl:choose>
      <xsl:when test="//Measure">
        <xsl:value-of select="count(//Measure)"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="1"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

 <xsl:variable name="msrsNodeSet" select="Reports/Report/Measures/Measure"/>

  <xsl:template match="Report" >

      <div id="g1" style="position: absolute; top: 0px; left: 0px; width: 400px; height: 12px">
        <table class="grdTop" border="0" cellspacing="1" cellpadding="0">
          <tbody>
            <xsl:apply-templates select="Columns" />
          </tbody>
        </table>
      </div>
   </xsl:template>

  <xsl:template match="text()"> </xsl:template>

  <xsl:template match="ColGrp" mode="counter">
    <xsl:param name="sofar" />
    <xsl:choose>
      <xsl:when test="Col">
        <xsl:value-of select="number($sofar)+1" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates select="ColGrp[1]" mode="counter">
          <xsl:with-param name="sofar" select="number($sofar)+1" />
        </xsl:apply-templates>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="Columns">
    <xsl:apply-templates select="ColGrp[1]" mode="Header">

      <xsl:with-param name="depth">
        <xsl:choose>
          <xsl:when test="$axisHeads='true'">
            <xsl:value-of select="0"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="1"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:with-param>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="ColGrp" mode="Header">
    <xsl:param name="depth" />
    <tr>

      <xsl:for-each select="//ColGrp[count(ancestor::ColGrp)=$depth]">
        <td colspan="{count(.//Col)*$msrs}" align="center" style="overflow:none">
          <nobr>
            <div>
              <xsl:value-of select="@heading"/>
            </div>
          </nobr>
        </td>
      </xsl:for-each>
    </tr>
    <xsl:choose>
      <xsl:when test="ColGrp">
        <xsl:apply-templates select="ColGrp[1]" mode="Header">
          <xsl:with-param name="depth" select="$depth+1" />
        </xsl:apply-templates>
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates select="Col[1]" mode="colHead" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="Col" mode="colHead">
    <tr>
      <xsl:for-each select="ancestor::Columns//Col">
        <td colspan="{$msrs}" valign="top" align="center" style="overflow:none">
          <nobr>

            <div>
              <xsl:value-of select="@heading"/>
            </div>
          </nobr>
        </td>
      </xsl:for-each>
    </tr>
    <tr valign="bottom">
      <xsl:for-each select="//Col">
        <xsl:apply-templates select="//Measures">
          <xsl:with-param name="pos" select="position()" />
        </xsl:apply-templates>
      </xsl:for-each>
    </tr>
  </xsl:template>

  <xsl:template match="//Measures">
    <xsl:param name="pos" />
    <xsl:for-each select="Measure">
      <xsl:variable name="mPos">
        <xsl:value-of select="position()" />
      </xsl:variable>
      <td align="center">
        <nobr>
          <div class="action" style="width:90px; overflow:none" onclick="sortFullGrid({$mPos}, {$pos}, '{@class}')">
            <xsl:value-of select="@heading"/>
          </div>
        </nobr>
      </td>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>
 
Old January 24th, 2007, 01:41 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

The most obvious inefficiency in your stylesheet is:

<xsl:for-each select="//ColGrp[count(ancestor::ColGrp)=$depth]">

I haven't tried to follow your logic here. I can't immediately see why you can't make a downward selection from the context node rather than searching the whole document. But if you must search the whole document, then as with any expression of the form

//X[Y=$p]

you can replace it with

key('k', $p)

where the key is defined as

<xsl:key name="k" match="X" use="Y"/>



Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old January 24th, 2007, 02:38 PM
Friend of Wrox
 
Join Date: Oct 2003
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default

I am sorry but I posted the wrong xml. This is the right one:

<?xml version="1.0"?>
<Reports xmlns="">
  <Report>
    <Measures>
      <Measure idx="1" heading="Total Ads"/>
    </Measures>
    <Columns>
      <ColGrp heading="Month">
        <ColGrp heading="2003">
          <ColGrp heading="Quarter 1">
            <Col heading="January"/>
            <Col heading="February"/>
            <Col heading="March"/>
          </ColGrp>
          <ColGrp heading="Quarter 2">
            <Col heading="April"/>
            <Col heading="May"/>
            <Col heading="June"/>
          </ColGrp>
          <ColGrp heading="Quarter 3">
            <Col heading="July"/>
            <Col heading="August"/>
            <Col heading="September"/>
          </ColGrp>
          <ColGrp heading="Quarter 4">
            <Col heading="October"/>
            <Col heading="November"/>
            <Col heading="December"/>
          </ColGrp>
        </ColGrp>
        <ColGrp heading="2004">
          <ColGrp heading="Quarter 1">
            <Col heading="January"/>
            <Col heading="February"/>
            <Col heading="March"/>
          </ColGrp>
          <ColGrp heading="Quarter 2">
            <Col heading="April"/>
            <Col heading="May"/>
            <Col heading="June"/>
          </ColGrp>
          <ColGrp heading="Quarter 3">
            <Col heading="July"/>
            <Col heading="August"/>
            <Col heading="September"/>
          </ColGrp>
          <ColGrp heading="Quarter 4">
            <Col heading="October"/>
            <Col heading="November"/>
            <Col heading="December"/>
          </ColGrp>
        </ColGrp>
      </ColGrp>
    </Columns>
  </Report>
</Reports>
 
Old January 24th, 2007, 02:52 PM
Friend of Wrox
 
Join Date: Oct 2003
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default

Hi Michale,

Thanks for your reply.

I have created this key in my xslt. I hope it is right.

 <xsl:key name="c" match="ColGrp" use="count(ancestor::ColGrp)"/>

However, I am not sure what the second argument to the key shoule be. This is what you showed me:

key('k', $p)

So, shall I use this:

key('c', $depth)

The whole thing then would be:

<xsl:key name="c" match="ColGrp" use="count(ancestor::ColGrp)"/>

<xsl:template match="ColGrp" mode="Header">
    <xsl:param name="depth" />
    <tr>

      <xsl:for-each select="key('c', $depth)">
        <td colspan="{count(.//Col)*$msrs}" align="center" style="overflow:none">
          <nobr>
            <div>
              <xsl:value-of select="@heading"/>
            </div>
          </nobr>
        </td>
      </xsl:for-each>
    </tr>
    <xsl:choose>
      <xsl:when test="ColGrp">
        <xsl:apply-templates select="ColGrp[1]" mode="Header">
          <xsl:with-param name="depth" select="$depth+1" />
        </xsl:apply-templates>
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates select="Col[1]" mode="colHead" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


Cheers,

CPall
 
Old January 24th, 2007, 03:05 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Yes, that's right.

But please bear in mind I just spotted one possible inefficiency in your code. I really haven't tried to understand what you are trying to do or whether your algorithm makes sense.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old January 24th, 2007, 03:49 PM
Friend of Wrox
 
Join Date: Oct 2003
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default

ok, Michael. Thanks a lot. Anything to help to speed it up is appreciated.

Basically, this is the output I get for 2003 and so on for 2004:

                             2003 2004..

         Quarter 1 Quarter 2 ...

 January February March April January February ...
Total Ads Total Ads Total Ads Total Ads Total Ads Total Ads

As I mentioned before, the code I wrote works but is very slow. The logic was right and I managed to achieve the desired result.

I hope the key you showed me will improve the performance for bigger xml.

If you see any other improvements I could make to the code, I would appreciate very much if you let me know.

I am not sure if this is too much to ask but I would appreciate if you could run the code and see if you can spot any more inefficiencies.

I never had such a complicated xslt to write and would appreciate to learn the best technique to produce a grid with many dimension.

Cheers,

CPall





Similar Threads
Thread Thread Starter Forum Replies Last Post
Slow Searching zaheer131 VB How-To 0 March 15th, 2005 03:26 AM
Loading too slow chiholi Crystal Reports 0 November 16th, 2004 02:52 AM
MSDE SLOW JENKINSACTIVE SQL Server 2000 1 October 28th, 2004 09:01 AM
Slow performance Stanny Access 1 August 26th, 2004 01:11 AM





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