Subject: Re: [xsl] passing filtered tree to template From: Stefan Hunziker <stefan@xxxxxxxxxxxxx> Date: Thu, 16 Jun 2011 11:34:27 +0200 |
Hi Brandon I have implemented your approach and it works perfectly Thank you very much Stefan On Thu, Jun 9, 2011 at 2:17 PM, Brandon Ibach <brandon.ibach@xxxxxxxxxxxxxxxxxxx> wrote: > Here's an approach that works while keeping the "criteria" for which > items to include in the caller. No guarantees about how the > performance of this approach might scale. Features in XSLT 3.0 (or > even XSLT 2.0, I suspect) would make this cleaner and probably perform > better. > > The xsl:for-each inside your "items" template basically turns it into > an "item" template, so I cleaned it up a bit by just making the > template match "item" and moving the test to determine of the item is > the first in its group into an xsl:if. I also made the code more > concise by using attribute value templates, but this is purely a > matter of taste, rather than functionality. > > Your "property = 'x'" filter also needs to be applied to any results > of the key() function. I did this below, while keeping the filter out > of the "item" template, by passing in the filtered set of items and > checking for group membership using the same basic technique you used > for node identity when checking to see if an item is the first in its > group. > > <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> > <xsl:template match="test"> > <myTest> > <xsl:variable name="items" select="items/item[property = 'x']"/> > <xsl:apply-templates select="$items"> > <xsl:sort select="group"/> > <xsl:with-param name="items" select="$items"/> > </xsl:apply-templates> > </myTest> > </xsl:template> > > <xsl:key name="groupKey" match="item" use="group"/> > <xsl:template match="item"> > <xsl:param name="items" select="/.."/> > <xsl:if test="count(. | key('groupKey', group)[count(. | > $items) = count($items)][1]) = 1"> > <myGroup Name="{group}" > Sum="{sum(key('groupKey',group)[count(. | $items) = > count($items)]/amount)}"/> > </xsl:if> > </xsl:template> > </xsl:stylesheet> > > Hope this helps. > > -Brandon :) > > > On Tue, Jun 7, 2011 at 2:34 AM, Stefan Hunziker <stefan@xxxxxxxxxxxxx> wrote: >> Hi Abel >> >> thank you for your answer. Sorry when my instructions were confusing. >> I give it another try, in fact the items template is a little bit more >> complicated because I want to apply a grouping mechanism. >> >> given the following xml: >> >> <test> >> <items> >> <item> >> <index>1</index> >> <group>b</group> >> <property>x</property> >> <amount>1</amount> >> </item> >> <item> >> <index>2</index> >> <group>a</group> >> <property>y</property> >> <amount>3</amount> >> </item> >> <item> >> <index>3</index> >> <group>a</group> >> <property>x</property> >> <amount>6</amount> >> </item> >> </items> >> </test> >> >> I want to process this stylesheet: >> >> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> >> <xsl:template match="test"> >> <myTest> >> <xsl:variable name="xItems"> >> <xsl:copy-of select="items"/> >> </xsl:variable> >> <xsl:apply-templates select="items[item/property='y']"/> >> </myTest> >> </xsl:template> >> >> <xsl:key name="groupKey" match="item" use="group"/> >> <xsl:template match="items"> >> <xsl:for-each select="item[count(.| key('groupKey', group)[1]) = 1]"> >> <xsl:sort select="group"/> >> <myGroup> >> <xsl:attribute name="Name"> >> <xsl:value-of select="group"/> >> </xsl:attribute> >> <xsl:attribute name="Sum"> >> <xsl:value-of select="sum(key('groupKey',group)/amount)"/> >> </xsl:attribute> >> </myGroup> >> </xsl:for-each> >> </xsl:template> >> </xsl:stylesheet> >> >> >> So the target is to have a group list with the corresponding sum of >> amount, so I don't have a "item" template, but only an "items". But >> therefore only the property=x items should be processed. Is that more >> clear? >> >> kind regards >> Stefan >> >> >> >> On Mon, Jun 6, 2011 at 6:11 PM, Abel Braaksma <abel.online@xxxxxxxxx> wrote: >>> Hi Stefan, >>> >>> The easy way out here is to add the filter to the matching template >>> instruction, and add another matching template for those that don't match, >>> or, if all "item" elements need to be processed in the same way, but item >>> with property=x need to be processed with an extra instruction, something >>> like this should work: >>> >>> <xsl:template match="items"> >>> <xsl:apply-templates select="item" /> >>> </xsl:template> >>> >>> <!-- called ONLY when property X is true --> >>> <xsl:template match="item[property='x']"> >>> <myItem> >>> <xsl:value-of select="index"/> >>> </myItem> >>> </xsl:template> >>> >>> <!-- called for all other situations (may leave empty if you don't want to >>> process them) --> >>> <xsl:template match="item"> >>> <otherItem> >>> <xsl:value-of select="index"/> >>> </otherItem> >>> </xsl:template> >>> >>> I have to note that I found your instruction a tad confusing, so if I >>> misunderstood, please try to clarify with a simplified input/output example >>> of XML. >>> >>> >>> Kind regards, >>> >>> Abel Braaksma >>> >>> >>> >>> On 6-6-2011 17:56, Stefan Hunziker wrote: >>>> >>>> Hi >>>> I have the following problem: Given an xml like the following: >>>> >>>> <test> >>>> <items> >>>> <item> >>>> <index>1</index> >>>> <property>x</property> >>>> </item> >>>> <item> >>>> <index>2</index> >>>> <property>y</property> >>>> </item> >>>> <item> >>>> <index>3</index> >>>> <property>x</property> >>>> </item> >>>> </items> >>>> </test> >>>> >>>> >>>> and a stylesheet like: >>>> >>>> >>>> <xsl:stylesheet version="1.0" >>>> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> >>>> <xsl:template match="test"> >>>> <myTest> >>>> <xsl:variable name="xItems"> >>>> <xsl:copy-of select="items"/> >>>> </xsl:variable> >>>> <xsl:apply-templates >>>> select="items[item/property='y']"/><!-- wrong try! --> >>>> </myTest> >>>> </xsl:template> >>>> >>>> <xsl:template match="items"> >>>> <xsl:for-each select="item"> >>>> <myItem> >>>> <xsl:value-of select="index"/> >>>> </myItem> >>>> </xsl:for-each> >>>> </xsl:template> >>>> </xsl:stylesheet> >>>> >>>> >>>> >>>> I would like to pass only the items with property='x' to the items >>>> matching template. The first try as written above of course doesn't >>>> work, if there is an x item then the whole tree is passed, if there is >>>> none, nothing is passed. I do further processing in the items >>>> template, so I don't want to change it to match="item" or to apply the >>>> filter in the items template. >>>> >>>> Any help is much appreciated! >>>> >>>> thanks, kind regards >>>> >>>> Stefan > > -- **************************** stefan hunziker kanalweg 10 ch-3315 bdtterkinden tel +41 32 665 17 76 mob +41 79 455 30 62 email stefan@xxxxxxxxxxxxx
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] passing filtered tree to , Stefan Hunziker | Thread | [xsl] Why is an empty xmlns="" adde, Alex Muir |
Re: [xsl] compare string to a list , Florent Georges | Date | AW: [xsl] compare string to a list , Szabo, Patrick \(LNG |
Month |