Xslt matches the first x elements of a filtered result set

Quite new for xslt so forgive me if this is the main question - I can not find the answer to either SO or Google search.

What I'm trying to do is return a filtered set of nodes, and then map the template to the first 1 or 2 elements of this set, and the other template matches the remainder. However, I cannot do this without a loop <xsl:for-each />(which is highly undesirable, since I can map 3000 nodes and process only 1).

Usage position()does not work, as this does not affect filtering. I tried sorting the result set, but this does not seem to work early enough to affect template matching. <xsl:number />outputs the correct numbers, but I cannot use them in the matching statement.

I will give an example code below. I use the wrong method to illustrate the problem position().

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:template match="*" />
</xsl:stylesheet>

Desired Result:

  • Heading 1
  • Heading 2
  • Header 5
+3
source share
1 answer

It is actually easier than you think. At:

 <xsl:template match="newsItem[string(title)][position() &lt; 4]">

And remove the predicate [string (title)] from yours <xsl:apply-templates.

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>

, , - ([position() &lt; 4]) [string(title)], position() .

+6

Source: https://habr.com/ru/post/1793623/


All Articles