开发者

Listing elements returned by group by xslt

开发者 https://www.devze.com 2023-03-01 23:16 出处:网络
Hi I have the following xml <?xml version=\"1.0\" encoding=\"UTF-8\"?> <root> <item> <name>john</name>

Hi I have the following xml

<?xml version="1.0" encoding="UTF-8"?>
<root>
<item>
<name>john</name>
<year>2010</year>
</item>
<item>
<name>sam</name>
<year>2000</year>
</item>
<item>
<name>jack</name>
<year>2007</year>
</item>
<item>
<name>smith</name>
<year>2010</year>
</item>
</root>

I use the following xslt to group by year

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
<xsl:template match="/">
<xsl:for-each-group select="r//*[(name=*)]" group-by="year">
<xsl:sort select="year" order="descending"/>
<xsl:variable name="total" select="count(/r//*[(name=*)]) + 1" />
    <xsl:value-of select="year"/><br />
    <xsl:for-each select="current-group()/name">
        <xsl:variable name="i" select="position()"/>    
        <xsl:call-template name="row">
            <xsl:with-param name="name" select="."/>
            <xsl:with-param name="number" select="$total - $i"/>
        </xsl:call-template>
    </xsl:for-each>
    <br />
</xsl:for-each-group>
</xsl:开发者_Go百科template>

<xsl:template name="row">
<xsl:param name="name"/>
<xsl:param name="number"/>
        <xsl:value-of select="concat($number, '. ')"/>
        <xsl:value-of select="concat($name, ' ')"/><br />
</xsl:template>
</xsl:stylesheet>

This is outputing, it's quite close to the output i want.

2010 
4. john 
3. smith 

2007 
4. jack 

2000
4. sam

What i want is simply numbering all names (descending order from total number of names to 1) e.g

2010
4. john 
3. smith 

2007
2. jack 

2000
1. sam

It would be simple if we can reassign a varible to a new value, but i thinks it's not possible, so i have to find another solution. Can anyone help me to find out how to resolve this problem.

thanks


Here is an XSLT-1.0 solution:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output type="text" omit-xml-declaration="yes"/>
    <xsl:key name="byYear" match="item" use="year"/>
    <xsl:template match="/">
        <!-- process first item for each distinct year number (ordered) -->
        <xsl:apply-templates select="//item[count(.|key('byYear',year)[1])=1]">
            <xsl:sort select="year" order="descending"/>
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="item">
        <!-- output year number, surrounded by newlines -->
        <xsl:text>
</xsl:text>
        <xsl:value-of select="year"/>
        <xsl:text>
</xsl:text>
        <!-- now process all items for the current year number -->
        <xsl:for-each select="key('byYear',year)">
            <!-- output reversed index of current item for current year number
                 plus total items for lower year numbers -->
            <xsl:number value="count(//item[year &lt; current()/year])+last()-position()+1"
                 format="1. "/>
            <!-- and finally also the name of the current item and again a newline -->
            <xsl:value-of select="name"/>
            <xsl:text>
</xsl:text>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>
0

精彩评论

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