xslt matching first x items of filtered result set
Quite new to xslt so forgive me if this is a basic question - I can't find the answer either on SO or by searching on Google.
What I am trying to do is return a filtered set of nodes and then have a template match on the first 1 or 2 items in that set and another template match the remainder. However I don't seem to be able to do this without a <xsl:for-each />
loop (which is highly undesirable as I may be matching 3000 nodes and only treating 1 differently).
Using position()
doesn't work as this is unaffected by the filtering. I've tried sorting the result set but this doesn't seem to take effect early enough to affect the template match. The <xsl:number />
outputs the correct numbers but I can't use these in a match statement.
I've put some example code below. I'm using the unsuitable position()
method below to illustrate the problem.
Thanks in advance!
XML:
<?xml version="1.0" encoding="utf-8"?>
<news>
<newsItem id="1">
<title>Title 1</title>
</newsItem>
<newsItem id="2">
<title>Title 2</title>
</newsItem>
<newsItem id="3">
<title></title>
</newsItem>
<newsItem id="4">
<title></title>
</newsItem>
<newsItem id="5">
<title>Title 5</title>
</newsItem>
</news>
XSL:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<ol>
<xsl:apply-templates select="/news/newsItem [string(title)]" />
</ol>
</xsl:template>
<xsl:template match="newsItem [position() < 4]">
<li>
<xsl:value-of select="title"/>
</li>
</xsl:template>
<xsl:开发者_如何学Ctemplate match="*" />
</xsl:stylesheet>
Desired Result:
- Title 1
- Title 2
- Title 5
This one's actually simpler than you might think. Do:
<xsl:template match="newsItem[string(title)][position() < 4]">
And drop the [string(title)] predicate from your <xsl:apply-templates
select.
Like this:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<ol>
<xsl:apply-templates select="/news/newsItem" />
</ol>
</xsl:template>
<xsl:template match="newsItem[string(title)][position() < 4]">
<li><xsl:value-of select="position()" />
<xsl:value-of select="title"/>
</li>
</xsl:template>
<xsl:template match="*" />
</xsl:stylesheet>
What you're effectively doing here is applying a second filter ([position() < 4]
) after your [string(title)]
filter, which results in the position()
being applied to the filtered list.
精彩评论