Subject: Re: [xsl] Newbie needs help with sorting a filtered list From: "James A. Robinson" <jim.robinson@xxxxxxxxxxxx> Date: Sun, 28 Jan 2007 21:41:37 -0800 |
> I'm hitting a wall over something that's probably stupid and > obvious. Please be patient with me! It's not stupid to ask questions if you don't understand something. > This gives me the correct items, but not in alphabetical order: > > <xsl:param name="param1"/> > <xsl:param name="param2"/> > > <xsl:template match="catalog/entry"> > <xsl:if test="category[@type=$param1] and category[@subcat=$param2]"> > <xsl:for-each select="word"> > <xsl:sort/> > <xsl:apply-templates/><br/> > </xsl:for-each> > </xsl:if> > </xsl:template> I think the problem you're having is regarding the way the xml document is being handled like a tree, and how the context available to you at each point in the tree changes as the processor executes your program. So you've got a template which matches every catalog/entry, when the template is activated it then tests to see if it has a sub element named category with the appropriate type and subcat attributes, and you tell it to select "every" word element. But you only have one word element per catalog/entry. So you are asking the XSLT engine to sort a list containing one item. First the template encounters <catalog> <entry> <word>orange</word> then it encounters <catalog> <entry> <word>spinach</spinach> And so forth. While your logic properly identifies that, due to the categories, you want'orange' and not 'spinach', each time you encounter a word you don't have any context to select and sort the other words. >From the point of view of the program it sees select 'orange' sort it (since it is only 1 item it just returns itself) apply-templates select 'apple' sort it (since it is only 1 item it just returns itself) apply-templlates select 'banana' sort it (since it is only 1 item it just returns itself) apply-templates > This one gives me an alphabetized list, but of all the items, not > just the ones that match the params: > > <xsl:template match="catalog"> > <xsl:if test="entry/category[@type=$param1] and > entry/category[@subcat=$param2]"> > <xsl:for-each select="entry/word"> > <xsl:sort/> > <xsl:apply-templates/><br/> > </xsl:for-each> > </xsl:if> > </xsl:template> Here you are matching an item at a higher level, at the catalog level. So now you have access to all the word elements. But your test isn't looping through each entry to check for its category: <xsl:template match="catalog"> <xsl:if test="entry/category[@type=$param1] and entry/category[@subcat=$param2]"> is simply checking to see if *an* entry/category with the parameters you specify exist. Since it does, the logic inside is executed, and then <xsl:for-each select="entry/word"> select *every* word. In other words if an entry/catalog matching @type=$param1 and @subcat=$param2 exists in my list then select all entry/word items in my list. sort the list of all word elements. apply-templates to the list of all word elements. > What am I doing wrong, and why do these two versions, which to my > rank amateur brain look like they should be the same, return such > different results? Because you are specifying a template which matches at a different point in the tree, your logic will need to be changed to identify what it is you want to process. You haven't shown how you are calling the templates, whether you are letting the processor walk through the entire document or whether you are driving it somehow. Here's one way you could structure the program, assuming you can tell program to match on catalog: <xsl:template match="catalog"> <xsl:apply-templates select="entry[category[@type=$param1 and @subcat=$param2]]"> <xsl:sort select="word"/> </xsl:apply-templates> </xsl:template> <xsl:template match="entry"> <xsl:apply-templates select="word"/><br/> </xsl:template> This assumes that 'catalog' will be matched and that it will be the only template which in turns selects catalog/entry items. It says "starting at catalog, I want to process all entry elements which have a child category element which in turn has type and subcat attributes equal to..." That gives you access to all the 'entry' elements which match your type and subcat. you can then sort on the word. A match on 'entry', simply serves to apply templates to the word and emits the <br/> tag. There are other ways you could structure this, but the important thing to remember is that you need sort things from a context which has all of the words you want available to it. Jim - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - James A. Robinson jim.robinson@xxxxxxxxxxxx Stanford University HighWire Press http://highwire.stanford.edu/ +1 650 7237294 (Work) +1 650 7259335 (Fax)
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] Newbie needs help with sortin, M. Casey | Thread | RE: [xsl] Newbie needs help with so, Michael Kay |
Re: [xsl] Newbie needs help with so, G. Ken Holman | Date | [xsl] xinclude in xslt 2.0 now avai, Erik Wilde |
Month |