开发者

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() &lt; 4]">
        <li>
            <xsl:value-of select="title"/>
        </li>
    </xsl:template>

    <xsl:开发者_如何学Ctemplate match="*" />
</xsl:stylesheet>

Desired Result:

  1. Title 1
  2. Title 2
  3. Title 5


This one's actually simpler than you might think. Do:

 <xsl:template match="newsItem[string(title)][position() &lt; 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() &lt; 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() &lt; 4]) after your [string(title)] filter, which results in the position() being applied to the filtered list.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜