Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to display a fixed number of elements? 2

Status
Not open for further replies.

BeckD

Programmer
Apr 16, 2002
53
GB
Hi

I have an xml page which is database driven (asp). In my xsl page I only want to display the first 5 articles. Something like:

--xml page
<page>
<article>
<title>Test</title>
<body>blah blah blah labhabl hb</body>
</article>
<article>
<title>Test</title>
<body>blah blah blah labhabl hb</body>
</article>
<article>
<title>Test</title>
<body>blah blah blah labhabl hb</body>
</article>
<article>
<title>Test</title>
<body>blah blah blah labhabl hb</body>
</article>
--etc
</page>

--xsl - this bit only wants to select the first 5 articles although the code I've put doesn't work
<xsl:for-each select=&quot;/page/article[count = 5]&quot;>
<xsl:value-of select=&quot;title&quot; />
</xsl:for-each>

If you get my drift...

I have found an example which works with the working draft xsl namespace, but it won't work with the namespace I'm using (<xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot; and I don't really want to go backwards and use the working draft. This code is:

<xsl:choose>
<xsl:when expr=&quot;childNumber(this) > 5&quot;></xsl:when>
<xsl:eek:therwise>
<xsl:value-of select=&quot;/page/article/title&quot; />
</xsl:eek:therwise>
</xsl:choose>

Grateful in advance for any comments/suggestions...
 
try:


<xsl:for-each select=&quot;/page/article&quot;>
<xsl:choose>
<xsl:when expr=&quot;count() > 5&quot;></xsl:when>
<xsl:eek:therwise>
<xsl:value-of select=&quot;title&quot; />
</xsl:eek:therwise>
</xsl:choose>
<xsl:for-each>

... you're lagging it a bit by doing nothing for the rest of the cycles but at least it should work...

You cant do for-each select=&quot;/page/article[count() > 5]&quot; because [] indicates node expressions and directly correlates to the nodes you are selecting, not the context within which you are working (unlike count, which is only operational within a context).

Another, more processor friendly way to do it, is to provide an identifying tag within your xml with which you can display a range of data from, eg:

<page>
<article number=&quot;1&quot;>
<title>Test</title>
<body>blah blah blah labhabl hb</body>
--etc
</page>


and then provide the template

<xsl:template select=&quot;//article[@number < 5]&quot;>
<xsl:value-of select=&quot;title&quot;/>
</xsl:template>

.. this should do unless you are dynamically updating or randomly updating articles within the xml.

hope this helps, let me know if you have any other questions :)

matt

 
Hi Matt

Thanks for your help, but I get the following error:

msxml3.dll error '80004005'

Attribute 'expr' is invalid on 'xsl:when'.

/xml/index.asp, line 68

(NB: index.asp line 68 is an asp file which parses the xml and xsl file)
 
ag, i cut and paste your example in and forgot that the /transform namespace in when doesnt support expr! :(

it should be

<xsl:for-each select=&quot;/page/article&quot;>
<xsl:choose>
<xsl:when test=&quot;count() > 5&quot;></xsl:when>
<xsl:eek:therwise>
<xsl:value-of select=&quot;title&quot; />
</xsl:eek:therwise>
</xsl:choose>
<xsl:for-each>

soz
 
plus make sure you use & gt; instead of an &quot;>&quot;!!!
 
I'm still getting an error: -

msxml3.dll error '80004005'

Expression expected. count(-->)<-- > 5

/xml/index.asp, line 68

Just to check with you that I'm not doing anything stupid, here's the code I'm using:

<xsl:for-each select=&quot;/page/article&quot;>
<xsl:choose>
<xsl:when test=&quot;count() > 5&quot;></xsl:when>
<xsl:eek:therwise>
<p><span class=&quot;headline&quot;><xsl:value-of select=&quot;title&quot;/></span></p>
</xsl:eek:therwise>
</xsl:choose>
</xsl:for-each>
 
doh.

put a '.' inside the brackets of count(), eg &quot;[count(.) > 5]&quot;

that should do it.

(mental note, always check your answers before posting :)

 
Sorry Matt - it still doesn't work. Am now getting:

msxml3.dll error '80004005'

Expression expected. <--

/xml/index.asp, line 68

I've tried putting:

<xsl:when test=&quot;count(.) > 5&quot;></xsl:when>
or
<xsl:when test=&quot;count(/page/article) > 5&quot;></xsl:when>
or
<xsl:when test=&quot;[count(.) > 5]&quot;></xsl:when>

and I get the same error with all.


 
are you using & gt; (remove the space) and not > in your expression? This is my working example on my debugger:

<xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot; <xsl:template match=&quot;/&quot;>

<xsl:for-each select=&quot;/page/article&quot;>
<xsl:choose>
<xsl:when test=&quot;count(.) & gt; 5&quot;></xsl:when>
<xsl:eek:therwise>
<p>
<span class=&quot;headline&quot;>
<xsl:value-of select=&quot;title&quot;/>
</span>
</p>
</xsl:eek:therwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Remember to remove the space if you cut n paste this from & gt; ..

matt
 
AGGGG

dont use count(.) use position().


so sorry about that. its monday :(

 
Try This one
XML:
<?xml version=&quot;1.0&quot; ?>
<table>
<row>Row#1</row>
<row>Row#2</row>
<row>Row#3</row>
<row>Row#4</row>
<row>Row#5</row>
<row>Row#6</row>
<row>Row#7</row>
<row>Row#8</row>
<row>Row#9</row>
<row>Row#10</row>
</table>

XSL:
<?xml version=&quot;1.0&quot;?>
<xsl:stylesheet version=&quot;1.0&quot;
xmlns:xsl=&quot; <xsl:eek:utput method=&quot;html&quot; encoding=&quot;Windows-1252&quot; />
<xsl:param name=&quot;Page&quot; select=&quot;2&quot; />
<xsl:param name=&quot;PageSize&quot; select=&quot;5&quot; />
<xsl:template match=&quot;table&quot;>
<html>
<head></head>
<body>
<xsl:variable name=&quot;RowCount&quot; select=&quot;count(row)&quot; />
<xsl:variable name=&quot;Pages&quot; select=&quot;ceiling($RowCount div $PageSize)&quot; />
<xsl:variable name = &quot;page&quot;>
<xsl:choose>
<xsl:when test=&quot;($Page > $Pages) or ($Page <= 0)&quot;>1</xsl:when>
<xsl:eek:therwise><xsl:value-of select=&quot;$Page&quot; /></xsl:eek:therwise>
</xsl:choose>
</xsl:variable>
Number Of Rows
<xsl:value-of select=&quot;$RowCount&quot; />
<BR />

Total Pages =
<xsl:value-of select=&quot;$Pages&quot; />

<xsl:for-each select=&quot;row[(position() <= $PageSize * $page and position() > $PageSize * ($page -1 ))]&quot;>
<div><xsl:value-of select=&quot;.&quot; /></div>
</xsl:for-each>

<xsl:call-template name=&quot;for.loop&quot;>
<xsl:with-param name=&quot;i&quot;>1</xsl:with-param>
<xsl:with-param name=&quot;count&quot; select=&quot;$Pages&quot; />
<xsl:with-param name=&quot;current&quot; select=&quot;$page&quot; />
</xsl:call-template>
</body>
</html>
</xsl:template>

<xsl:template name=&quot;for.loop&quot;>
<xsl:param name=&quot;i&quot; />

<xsl:param name=&quot;count&quot; />

<xsl:param name=&quot;current&quot; />

<xsl:if test=&quot;$i <= $count&quot;>
<xsl:choose>
<xsl:when test=&quot;$i != $current&quot;><xsl:value-of select=&quot;$i&quot; /></xsl:when>
<xsl:eek:therwise><b><xsl:value-of select=&quot;$i&quot; /></b></xsl:eek:therwise>
</xsl:choose>
<xsl:if test=&quot;$i+1 <= $count &quot;>,</xsl:if>
</xsl:if>
<xsl:if test=&quot;$i <= $count&quot;>
<xsl:call-template name=&quot;for.loop&quot;>
<xsl:with-param name=&quot;i&quot; select=&quot;$i + 1&quot; />
<xsl:with-param name=&quot;count&quot; select=&quot;$count&quot; />
<xsl:with-param name=&quot;current&quot; select=&quot;$current&quot; />
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
------------------------------
 
anything you want, if you change the XML Nodes, do the same with XSL.
 
I may be being dumb here, but I don't really understand what you're getting at. If you're tring to do the same thing, then isn't the way that Matt already suggested shorter, simpler and more efficient?
 
i have a question:
could you have done something like

<xsl:for-each select=&quot;/page/article[position()<5]&quot;>
<xsl:value-of select=&quot;title/>
</xsl:for-each>

wouldn't this be faster than iterating through every article and evaluating an expression?

mike griffith
----------------------------
mgriffith@lauren.com
mdg12@po.cwru.edu
 
yes.

erm.

:)

the only drawback would be if you wanted to do something if the value was greater than 5, like display a break or something.

apart from that, thats a nice elegant solution.

I think i must have been half asleep when I answered the original question.. I dont know where my head was at that day :(

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top