Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > XML > XSLT reduce or count number of matching output elements

Reply
Thread Tools

XSLT reduce or count number of matching output elements

 
 
Marcel Akkerman
Guest
Posts: n/a
 
      02-21-2004

Hi,

Does anyone have a clue how to reduce the number of nodes using XSLT?
When outputing all nodes in order I could just use
<xsl:for-each select="name[position & $someNumber]">

But what if I, besides sorting and grouping, I also output
conditionally?

<xsl:for-each
select="//name[generate-id(.)=generate-id(key('names',city))]">
<strong><xsl:value-of select="city"/></strong>
<xsl:for-each select="key('names',city)">
<xsl:sort select="date" order="ascending"/>
<xsl:if test="translate(date, '-', '') &gt; translate($afterDate, '-',
'')">
<xsl:value-of select="name"/><br>
</xsl:if>
</xsl:for-each>
</xsl:for-each>


With this transformation I can get the names of people who's birthday
is after a given date. The names are sorted by date and grouped by the
city.

What to do if I only want a total of $maximum result??

gratefull for anyhelp.

Marcel.
 
Reply With Quote
 
 
 
 
Dimitre Novatchev [MVP XML]
Guest
Posts: n/a
 
      02-22-2004

"Marcel Akkerman" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
>
> Hi,
>
> Does anyone have a clue how to reduce the number of nodes using XSLT?


Yes, you can reduce it completely by having:

<xsl:template match="/" />


> When outputing all nodes in order I could just use
> <xsl:for-each select="name[position & $someNumber]">


This is not well-formed xml -- what do you want to say?


>
> But what if I, besides sorting and grouping, I also output
> conditionally?
>
> <xsl:for-each
> select="//name[generate-id(.)=generate-id(key('names',city))]">
> <strong><xsl:value-of select="city"/></strong>
> <xsl:for-each select="key('names',city)">
> <xsl:sort select="date" order="ascending"/>
> <xsl:if test="translate(date, '-', '') &gt; translate($afterDate, '-',
> '')">
> <xsl:value-of select="name"/><br>
> </xsl:if>
> </xsl:for-each>
> </xsl:for-each>
>
>
> With this transformation I can get the names of people who's birthday
> is after a given date. The names are sorted by date and grouped by the
> city.


No, what would be output as result depends completely on the source xnl
document, which you haven't shown to us.


>
> What to do if I only want a total of $maximum result??


What does "a total of $maximum result" mean?

Please, alawys formulate well your problem if you really want to be
understood so that somebody could help.

A well-formulated problem includes the source xml document, the wanted
result of the transformation, (these two should completely describe the
problem, but be with minimal possible length and well indented so that they
are readable and understandable), a description of the desired properties of
the transformation.


Cheers,

Dimitre Novatchev [XML MVP],
FXSL developer, XML Insider,

http://fxsl.sourceforge.net/ -- the home of FXSL
Resume: http://fxsl.sf.net/DNovatchev/Resume/Res.html


 
Reply With Quote
 
 
 
 
Marcel Akkerman
Guest
Posts: n/a
 
      02-22-2004
On Sun, 22 Feb 2004 09:57:51 +0100, "Dimitre Novatchev [MVP XML]"
<(E-Mail Removed)> wrote:

>
>"Marcel Akkerman" <(E-Mail Removed)> wrote in message
>news:(E-Mail Removed).. .
>>
>> Hi,
>>
>> Does anyone have a clue how to reduce the number of nodes using XSLT?

>
>Yes, you can reduce it completely by having:
>
> <xsl:template match="/" />
>
>
>> When outputing all nodes in order I could just use
>> <xsl:for-each select="name[position & $someNumber]">

>
>This is not well-formed xml -- what do you want to say?

sorry
it just a fragment and supposed to be:
<xsl:for0each select="name[position $lt; %someNumber]">

>>
>> But what if I, besides sorting and grouping, I also output
>> conditionally?
>>
>> <xsl:for-each
>> select="//name[generate-id(.)=generate-id(key('names',city))]">
>> <strong><xsl:value-of select="city"/></strong>
>> <xsl:for-each select="key('names',city)">
>> <xsl:sort select="date" order="ascending"/>
>> <xsl:if test="translate(date, '-', '') &gt; translate($afterDate, '-',
>> '')">
>> <xsl:value-of select="name"/><br>
>> </xsl:if>
>> </xsl:for-each>
>> </xsl:for-each>
>>
>>
>> With this transformation I can get the names of people who's birthday
>> is after a given date. The names are sorted by date and grouped by the
>> city.

>
>No, what would be output as result depends completely on the source xnl
>document, which you haven't shown to us.


Fine, here's one with the irellevant data left out.

<people>
<person>
<name>Johnson</name>
<city>Boston</city>
<date>1965-02-05</date>
</person>
<person>
<name>Smit</name>
<city>Lutjebroek</city>
<date>1975-04-06</date>
</person>

<!-- etc. -->

</people>


Desired output (I get it this far)

Boston
Johnons
Peterson
Ackerman

Lutjebroek
Smit
Timmerman
de la Frost
Bos

Amsterdam
Lubbers
Veensma

This goes on as long as there are nodes in the original XML
What I want is to reduce the number names output to, let's say 5 in
total. This would look like:

Boston
Johnons
Peterson
Ackerman

Lutjebroek
Smit
Timmerman

An maybe reduce it to 2 per city. Which will look like:

Boston
Johnons
Peterson

Lutjebroek
Smit
Timmerman

Amsterdam
Lubbers
Veensma



-- hope you know what I'm after now
-- thanks for any help.

Marcel.
 
Reply With Quote
 
Marcel Akkerman
Guest
Posts: n/a
 
      02-22-2004
On Sun, 22 Feb 2004 12:10:30 +0100, Marcel Akkerman
<(E-Mail Removed)> wrote:

>On Sun, 22 Feb 2004 09:57:51 +0100, "Dimitre Novatchev [MVP XML]"
><(E-Mail Removed)> wrote:
>
>>
>>"Marcel Akkerman" <(E-Mail Removed)> wrote in message
>>news:(E-Mail Removed). ..
>>>
>>> Hi,
>>>
>>> Does anyone have a clue how to reduce the number of nodes using XSLT?

>>
>>Yes, you can reduce it completely by having:
>>
>> <xsl:template match="/" />
>>
>>
>>> When outputing all nodes in order I could just use
>>> <xsl:for-each select="name[position & $someNumber]">

>>
>>This is not well-formed xml -- what do you want to say?

>sorry
>it just a fragment and supposed to be:

<xsl:for-each select="name[position() &lt; $someNumber]">
 
Reply With Quote
 
Dimitre Novatchev [MVP XML]
Guest
Posts: n/a
 
      02-22-2004
> Fine, here's one with the irellevant data left out.
>
> <people>
> <person>
> <name>Johnson</name>
> <city>Boston</city>
> <date>1965-02-05</date>
> </person>
> <person>
> <name>Smit</name>
> <city>Lutjebroek</city>
> <date>1975-04-06</date>
> </person>
>
> <!-- etc. -->
>
> </people>
>
>
> Desired output (I get it this far)
>
> Boston
> Johnons
> Peterson
> Ackerman
>
> Lutjebroek
> Smit
> Timmerman
> de la Frost
> Bos
>
> Amsterdam
> Lubbers
> Veensma
>
> This goes on as long as there are nodes in the original XML
> What I want is to reduce the number names output to, let's say 5 in
> total. This would look like:
>
> Boston
> Johnons
> Peterson
> Ackerman
>
> Lutjebroek
> Smit
> Timmerman
>
> An maybe reduce it to 2 per city. Which will look like:
>
> Boston
> Johnons
> Peterson
>
> Lutjebroek
> Smit
> Timmerman
>
> Amsterdam
> Lubbers
> Veensma



This transformation:

<xsl:stylesheet version="1.0"
xmlnssl="http://www.w3.org/1999/XSL/Transform">

<xslutput method="text"/>

<xsl:key name="kdistCity" match="city" use="."/>
<xsl:key name="kNamesByCity" match="name" use="../city"/>

<xsl:template match="/">
<xsl:variable name="vCities" select=
"/*/*/city[generate-id()
=
generate-id(key('kdistCity', .)[1])
]"/>
<xsl:call-template name="dispNames">
<xsl:with-param name="pCities" select="$vCities"/>
<xsl:with-param name="pBornAfter" select="19650201"/>
<xsl:with-param name="pMaxNames" select="6"/>
<xsl:with-param name="pMaxNamesPerCity" select="2"/>
</xsl:call-template>
</xsl:template>

<xsl:template name="dispNames">
<xslaram name="pCities" select="/.."/>
<xslaram name="pBornAfter" select="0"/>
<xslaram name="pMaxNames" select="1000"/>
<xslaram name="pMaxNamesPerCity" select="100"/>
<xslaram name="ptotalDisplayed" select="0"/>

<xsl:variable name="vmore2Display"
select="$pMaxNames - $ptotalDisplayed"/>

<xsl:variable name="vthisCity" select="$pCities[1]"/>

<xsl:variable name="vnamesInThisCity" select=
"key('kNamesByCity', $vthisCity)
[translate(../date, '-', '')
>

$pBornAfter
]"/>
<xsl:variable name="vcntNamesInCity"
select="count($vnamesInThisCity)"/>

<xsl:if test="$vmore2Display > 0 and $pCities">
<xsl:variable name="vdispLimit" select=
"$pMaxNamesPerCity * ($vmore2Display > $pMaxNamesPerCity)
+
$vmore2Display * (not($vmore2Display > $pMaxNamesPerCity))
"/>

<xsl:value-of select="concat('&#xA;&#xA;', $vthisCity)"/>

<xsl:for-each select="$vnamesInThisCity">
<xsl:sort select="translate(../date, '-', '')"/>

<xsl:if test="position() &lt;= $vdispLimit">
<xsl:value-of select="concat('&#xA; ', .)"/>
</xsl:if>
</xsl:for-each>

<xsl:call-template name="dispNames">
<xsl:with-param name="pCities" select="$pCities[position() > 1]"/>
<xsl:with-param name="pBornAfter" select="$pBornAfter"/>
<xsl:with-param name="pMaxNames" select="$pMaxNames"/>
<xsl:with-param name="pMaxNamesPerCity" select="$pMaxNamesPerCity"/>
<xsl:with-param name="ptotalDisplayed" select=
"$ptotalDisplayed
+ $vdispLimit * ($vcntNamesInCity > $vdispLimit )
+ $vcntNamesInCity *(not($vcntNamesInCity > $vdispLimit))"/>

</xsl:call-template>

</xsl:if>

</xsl:template>
</xsl:stylesheet>

when applied on this source.xml:

<people>
<person>
<name>Johnson</name>
<city>Boston</city>
<date>1965-02-05</date>
</person>
<person>
<name>Smit</name>
<city>Lutjebroek</city>
<date>1975-04-06</date>
</person>
<person>
<name>Peterson</name>
<city>Boston</city>
<date>1965-02-05</date>
</person>
<person>
<name>Ackerman</name>
<city>Boston</city>
<date>1965-02-05</date>
</person>
<person>
<name>Timmerman</name>
<city>Lutjebroek</city>
<date>1975-04-06</date>
</person>
<person>
<name>de la Frost</name>
<city>Lutjebroek</city>
<date>1975-04-06</date>
</person>
<person>
<name>Bos</name>
<city>Lutjebroek</city>
<date>1975-04-06</date>
</person>
<person>
<name>Lubbers</name>
<city>Amsterdam</city>
<date>1975-04-06</date>
</person>
<person>
<name>Veensma</name>
<city>Amsterdam</city>
<date>1975-04-06</date>
</person>

<!-- etc. -->

</people>



produces the wanted result:

Boston
Johnson
Peterson

Lutjebroek
Smit
Timmerman

Amsterdam
Lubbers
Veensma

It has a total limit of 6 names and a limit of maximum 2 names per city.


Hope this helped.

Cheers,

Dimitre Novatchev [XML MVP],
FXSL developer, XML Insider,

http://fxsl.sourceforge.net/ -- the home of FXSL
Resume: http://fxsl.sf.net/DNovatchev/Resume/Res.html


 
Reply With Quote
 
Marcel Akkerman
Guest
Posts: n/a
 
      02-22-2004


>It has a total limit of 6 names and a limit of maximum 2 names per city.
>
>
>Hope this helped.


It sure does. Thanksalot!

Marcel
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
<Need Help>How to get the count of elements referencing another element in XSLT? njsimha XML 0 09-12-2008 02:47 PM
xslt: count elements... ralf321@gmx.de XML 4 12-09-2005 12:29 PM
better to compress the jpeg or reduce resolution or reduce pixel size? Mr.Will Digital Photography 8 10-08-2004 03:16 PM
Using XSLT to Filter out elements with CDATA matching a regular expression Edwin G. Castro XML 3 09-17-2004 05:12 PM
Is there a VAR to count the number of occurences of matching shrek11001 Perl Misc 6 10-28-2003 02:46 PM



Advertisments