 |
| 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
|
|
|
|

October 2nd, 2007, 01:11 PM
|
|
Registered User
|
|
Join Date: Oct 2007
Posts: 7
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
sorting and filtering oh my
Hope someone in here can help me with this one, its got me stumped.
I have XML data for a CD collection and a stylesheet that I have setup to sort it as need be (i.e. by artist, by album name, etc). However, since the library is rather large I want the stylesheet to be able to accept parameters for a range of items to return (say the first 100, or the last 50, or whatever). How can I accomplish this in conjunction with my sorting?
Here is some sample XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<library>
<album>
<ID>1234</ID>
<Name><![CDATA[Paul's Boutique]]></Name>
<Artist><![CDATA[The Beastie Boys]]></Artist>
<Genre><![CDATA[Rap/Hip-Hop]]></Genre>
<Rating>8.5</Rating>
</album>
<album>
<ID>5678</ID>
<Name><![CDATA[Document]]></Name>
<Artist><![CDATA[R.E.M]]></Artist>
<Genre><![CDATA[Rock]]></Genre>
<Rating>7</Rating>
</album>
<album>
<ID>9988</ID>
<Name><![CDATA[Kind Of Blue]]></Name>
<Artist><![CDATA[Miles Davis]]></Artist>
<Genre><![CDATA[Jazz]]></Genre>
<Rating>8.9</Rating>
</album>
</library>
And my stylesheet (note the variables I have declared for start and end index):
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output encoding="utf-8" method="xml" indent="yes"/>
<xsl:param name="startIndex" select="0" />
<xsl:param name="endIndex" select="10" />
<xsl:template match="library">
<xsl:copy>
<xsl:apply-templates>
<xsl:sort data-type="text" select="Artist" order="ascending"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
|
|

October 2nd, 2007, 01:34 PM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
Try replacing your match="*" template by
<xsl:template match="album">
<xsl:if test="position() > $startIndex and position() < $endIndex">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:template>
Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
|
|

October 2nd, 2007, 01:49 PM
|
|
Registered User
|
|
Join Date: Oct 2007
Posts: 7
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
thanx for the reply Michael but I was matching 'library' in my other template where I do my sort so if I change the '*' to 'library' i'd have both templates matching on the same thing.
Its really like I need to combine them into one so that it:
1)sorts the full xml according to my sort clause
2)then applies my filter to pull a range of records
so for example I could sort by artist ascending, then take records 10-20
|
|

October 2nd, 2007, 02:04 PM
|
|
Registered User
|
|
Join Date: Oct 2007
Posts: 7
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
but this appears to work! I like simple solutions, I think I was over thinking this one:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output encoding="utf-8" method="xml" indent="yes"/>
<xsl:param name="startIndex" select="3" />
<xsl:param name="endIndex" select="8" />
<xsl:template match="library">
<xsl:copy>
<xsl:apply-templates>
<xsl:sort data-type="text" select="Artist" order="ascending"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:if test="position() >= $startIndex and position() <= $endIndex">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
|
|

October 4th, 2007, 03:24 PM
|
|
Registered User
|
|
Join Date: Oct 2007
Posts: 7
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
damn, so close...this actually works exactly as it should as long as the xml looks just like my example. Unfortunately I overlooked a small detail. In addition to the album nodes under library the actual xml also contains some informational elements (it comes from a webservice, so for example it provides the total number or records, a status code, etc)
So because I have these additional nodes, my greedy template match on "*" will process those informational elements as well and count those in its processing, so I get bogus results for the start and end indices.
Anyone have any insight to how I can solve this?
|
|

October 4th, 2007, 06:25 PM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
I'm not sure why you're stumped - where have you been looking for information?
Just change <xsl:apply-templates> to <xsl:apply-templates select="Album"/>.
Could I suggest you do some reading around the language?
Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
|
|

October 5th, 2007, 10:54 AM
|
|
Registered User
|
|
Join Date: Oct 2007
Posts: 7
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
apologies, I could have sworn that was one of the first things I tried and it didn't work. I have a bunch of additional parameters I'm passing into my stylesheet and I suspect I had messed set wrong there and it was giving me weird results. I should have stripped it down to the basics to test, sorry. Thanx for your help
|
|
 |