XSLT for-each newbie problem

Discussion in 'XML' started by R, Mar 17, 2005.

  1. R

    R Guest

    Hello everybody.

    I've got a problem with one loop.

    Given XML:
    <Types>
    <Type><range>1</range><name>Gast</name></Type>
    <Type><range>2</range><name>Rekt</name></Type>
    <Type><range>2</range><name>Sigm</name></Type>
    <!-- range is 1-6 -->
    </Types>

    I want to produce HTML output like this (grouped by range):
    <li>Gast</li>
    <li>Rekt, Sigm</li>

    well I can produce the single <li> element for 'Gast and 'Rekt, Sigm'
    output but I don't know how to iterate through all the 'range'

    I did sth like:
    1) produce <li> for range='1'
    2) produce <li> for range='2'
    ....
    6) produce <li> for range='6'

    how to itrate through ranges from 1 to 6 automatically?
    I know that ranges are sorted, there cannot be 5 before 2 etc.

    this is my step-by-step version
    <xsl:template match="Types" mode="searching">
    <!-- do it for range='1' -->
    <li>
    <!-- variable needed for the comma -->
    <xsl:variable name="last">
    <xsl:value-of select="count(Type[./range='1'])"/></xsl:variable>
    <xsl:for-each select="Type[./range='1']">
    <xsl:value-of select="name"/>
    <xsl:if test="$last != position()">, </xsl:if>
    </xsl:for-each>
    </li>
    <li>
    <xsl:variable name="last">
    <xsl:value-of select="count(Type[./range='1'])"/></xsl:variable>
    <xsl:for-each select="Type[./range='1']">
    <xsl:value-of select="name"/>
    <xsl:if test="$last != position()">, </xsl:if>
    </xsl:for-each>
    </li>
    <!-- and for the rest of ranges 3, 4, 5, 6 the same -->
    </xsl:template>

    thanks for any help
    best regards R
     
    R, Mar 17, 2005
    #1
    1. Advertising

  2. R

    William Park Guest

    R <> wrote:
    > Hello everybody.
    >
    > I've got a problem with one loop.
    >
    > Given XML:
    > <Types>
    > <Type><range>1</range><name>Gast</name></Type>
    > <Type><range>2</range><name>Rekt</name></Type>
    > <Type><range>2</range><name>Sigm</name></Type>
    > <!-- range is 1-6 -->
    > </Types>
    >
    > I want to produce HTML output like this (grouped by range):
    > <li>Gast</li>
    > <li>Rekt, Sigm</li>


    Well, it's not XSLT, but this is what I would do using Expat parser and
    Bash shell:

    data () # Usage: data [1-6] or data [Gast|Rekt|...]
    {
    case ${XML_ELEMENT_STACK[1]} in
    range) range=$1 ;;
    name) name=$1 ;;
    esac
    }
    start () # Usage: start tag att=value ...
    {
    case $1 in
    Types) unset range{1..6} ;;
    Type) unset range name ;;
    esac
    }
    end () # Usage: end tag
    {
    case $1 in
    Type) declare -p range$range &>/dev/null && strcat range$range ", "
    strcat range$range $name ;;
    esac
    }

    xml -s start -e end -d data '<Types> ... </Types>'
    declare -p range{1..6}

    --
    William Park <>, Toronto, Canada
    Slackware Linux -- because it works.
     
    William Park, Mar 17, 2005
    #2
    1. Advertising

  3. R

    Ben LamHang Guest

    Had a look at it. I tried using xsl:if / xml:when / xml:eek:therwise / xml:sort
    to compare previous siblings and build the xml from there. However xml
    doesn't like when you leave an unterminated tag which you need to run
    through and stores 2 or more values between the same tags...
    So close to your code, you have to manually put the figures in...

    <?xml version="1.0" ?>
    <xsl:transform version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="Types">
    <li>
    <xsl:for-each select="Type[range='1']">
    <xsl:value-of select="name" /><xsl:if test="position()!=last()">,
    </xsl:if>
    </xsl:for-each>
    </li>

    <li>
    <xsl:for-each select="Type[range='2']">
    <xsl:value-of select="name" /><xsl:if test="position()!=last()">,
    </xsl:if>
    </xsl:for-each>
    </li>

    <li>
    <xsl:for-each select="Type[range='3']">
    <xsl:value-of select="name" /><xsl:if test="position()!=last()">,
    </xsl:if>
    </xsl:for-each>
    </li>

    <li>
    <xsl:for-each select="Type[range='4']">
    <xsl:value-of select="name" /><xsl:if test="position()!=last()">,
    </xsl:if>
    </xsl:for-each>
    </li>

    <li>
    <xsl:for-each select="Type[range='5']">
    <xsl:value-of select="name" /><xsl:if test="position()!=last()">,
    </xsl:if>
    </xsl:for-each>
    </li>

    <li>
    <xsl:for-each select="Type[range='6']">
    <xsl:value-of select="name" /><xsl:if test="position()!=last()">,
    </xsl:if>
    </xsl:for-each>
    </li>
    </xsl:template>

    </xsl:transform>

    "R" <> wrote in message
    news:...
    > Hello everybody.
    >
    > I've got a problem with one loop.
    >
    > Given XML:
    > <Types>
    > <Type><range>1</range><name>Gast</name></Type>
    > <Type><range>2</range><name>Rekt</name></Type>
    > <Type><range>2</range><name>Sigm</name></Type>
    > <!-- range is 1-6 -->
    > </Types>
    >
    > I want to produce HTML output like this (grouped by range):
    > <li>Gast</li>
    > <li>Rekt, Sigm</li>
    >
    > well I can produce the single <li> element for 'Gast and 'Rekt, Sigm'
    > output but I don't know how to iterate through all the 'range'
    >
    > I did sth like:
    > 1) produce <li> for range='1'
    > 2) produce <li> for range='2'
    > ...
    > 6) produce <li> for range='6'
    >
    > how to itrate through ranges from 1 to 6 automatically?
    > I know that ranges are sorted, there cannot be 5 before 2 etc.
    >
    > this is my step-by-step version
    > <xsl:template match="Types" mode="searching">
    > <!-- do it for range='1' -->
    > <li>
    > <!-- variable needed for the comma -->
    > <xsl:variable name="last">
    > <xsl:value-of select="count(Type[./range='1'])"/></xsl:variable>
    > <xsl:for-each select="Type[./range='1']">
    > <xsl:value-of select="name"/>
    > <xsl:if test="$last != position()">, </xsl:if>
    > </xsl:for-each>
    > </li>
    > <li>
    > <xsl:variable name="last">
    > <xsl:value-of select="count(Type[./range='1'])"/></xsl:variable>
    > <xsl:for-each select="Type[./range='1']">
    > <xsl:value-of select="name"/>
    > <xsl:if test="$last != position()">, </xsl:if>
    > </xsl:for-each>
    > </li>
    > <!-- and for the rest of ranges 3, 4, 5, 6 the same -->
    > </xsl:template>
    >
    > thanks for any help
    > best regards R
     
    Ben LamHang, Mar 18, 2005
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John Blair
    Replies:
    1
    Views:
    411
    Eliyahu Goldin
    Aug 3, 2005
  2. Tjerk Wolterink

    xsl:for-each for each 3 elements problem

    Tjerk Wolterink, Nov 3, 2004, in forum: XML
    Replies:
    3
    Views:
    429
    Tjerk Wolterink
    Nov 3, 2004
  3. Replies:
    1
    Views:
    1,746
  4. crabsdf
    Replies:
    0
    Views:
    757
    crabsdf
    Apr 29, 2008
  5. Pat Maddox
    Replies:
    6
    Views:
    157
    Marcin Mielżyński
    Jan 20, 2006
Loading...

Share This Page