Re: [xsl] passing filtered tree to template

Subject: Re: [xsl] passing filtered tree to template
From: Stefan Hunziker <stefan@xxxxxxxxxxxxx>
Date: Tue, 7 Jun 2011 08:34:42 +0200
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

Current Thread