Problems using the "following-sibling"-expression in XPATH

Discussion in 'XML' started by Peter Rohleder, Jun 27, 2003.

  1. Hi,

    I'm using a style-sheet where I make use of the
    XPATH-"following-sibling"-expression.

    The part which makes problems looks similar to the following code:

    ---------------------------

    <xsl:for-each select="headdata/extension/person">
    <xsl:choose>
    <xsl:when test="(position()) mod 3 = 1">
    <tr>
    <td>
    <!-- Part 1 works -->
    <xsl:text disable-output-escaping="yes">more info::</xsl:text>
    <xsl:value-of select="funktion"/>

    <!-- Part 2 works -->
    <xsl:call-template name="handlePerson">
    <xsl:with-param name="persondata" select="."/>
    </xsl:call-template>
    </td>

    <td>
    <!-- Part 3 works -->
    <xsl:text disable-output-escaping="yes">more info:</xsl:text>
    <xsl:value-of select="following-sibling::*[1]/funktion"/>

    <!-- Part 4 doens'nt work-->
    <xsl:call-template name="handlePerson">
    <xsl:with-param name="persondata"
    select="following-sibling::*[1]"/>
    </xsl:call-template>
    </td>

    (...)
    -----------------------------

    I'm in the process of selecting a couple of persons and I want to give
    the selected person to a sub-template which should do some processing.

    I can access subfields (using following-sibling-expression) of the
    current node (see Part 1).
    I can access the current node and give it as parameter to the template
    "handlePerson" and it works(see Part 2).

    I can access subfields of the next sibling (see Part 3) and it works.

    But I cannot give the next sibling as parameter to the template
    "handlePerson" (see Part 4).

    When giving the "following-sibling::*[1]" as parameter to the template
    "handlePerson" it always processes the current node; the same with all
    other following siblings.

    Does anybody have an idea what might be wrong?

    Thanks in advance

    Peter Rohleder
     
    Peter Rohleder, Jun 27, 2003
    #1
    1. Advertising

  2. Hi Marrow,

    you write:

    (...)
    > Perhaps if you post some example XML and describe what you are actually
    > trying to achieve? It is difficult to see what the problem might be from
    > just an incomplete fragment of XSLT code.
    >
    > I suspect you might be wanting to organize things into a table with a fixed
    > 3 coulumns?


    yes, thats true!

    I solved the problem by replacing following part, which doesn't work:

    >>
    >> <!-- Part 4 doens'nt work-->
    >> <xsl:call-template name="handlePerson">
    >> <xsl:with-param name="persondata"
    >> select="following-sibling::*[1]"/>
    >> </xsl:call-template>


    (...)

    by(new code):
    -----------
    <xsl:for-each select="following-sibling::*">
    <xsl:if test="position() &lt; 3">

    <td>
    <xsl:call-template name="handlePerson">
    <xsl:with-param name="persondata" select="."/> </xsl:call-template>
    </td>

    </xsl:if>
    </xsl:for-each>
    -----------

    Now it works, but i still have no idea why the code above doesn't work
    and the new code works.

    Thanks for your response.

    Peter Rohleder
     
    Peter Rohleder, Jun 28, 2003
    #2
    1. Advertising

  3. Peter Rohleder

    Marrow Guest

    Hi Peter,

    If you want to arrange something by a given number of fixed columns then
    something like...

    == XML =================================
    <?xml version="1.0"?>
    <headdata>
    <extension>
    <person>
    <name>Aaaa</name>
    <funktion>A1</funktion>
    </person>
    <person>
    <name>Bbbb</name>
    <funktion>B2</funktion>
    </person>
    <person>
    <name>Cccc</name>
    <funktion>C3</funktion>
    </person>
    <person>
    <name>Dddd</name>
    <funktion>D4</funktion>
    </person>
    <person>
    <name>Eeee</name>
    <funktion>E5</funktion>
    </person>
    </extension>
    </headdata>
    == end of XML ==========================

    == XSL1 =================================
    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:eek:utput method="html" indent="yes"/>
    <xsl:param name="no-cols" select="3"/>
    <xsl:template match="/">
    <html>
    <body>
    <table border="1">
    <xsl:apply-templates select="headdata/extension/person[position()
    mod $no-cols = 1 or $no-cols = 1]" mode="row-start"/>
    </table>
    </body>
    </html>
    </xsl:template>

    <xsl:template match="person" mode="row-start">
    <tr>
    <xsl:apply-templates select=". | following-sibling::person[position()
    &lt; $no-cols]"/>
    </tr>
    </xsl:template>

    <xsl:template match="person">
    <td>
    <xsl:value-of select="name"/>
    <br/>
    <xsl:text>more info: </xsl:text>
    <xsl:value-of select="funktion"/>
    </td>
    </xsl:template>
    </xsl:stylesheet>
    == end of XSL1 ==========================

    or...

    == XSL2 =================================
    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:eek:utput method="html" indent="yes"/>
    <xsl:param name="no-cols" select="3"/>
    <xsl:template match="/">
    <html>
    <body>
    <table border="1">
    <xsl:for-each select="headdata/extension/person[position() mod
    $no-cols = 1 or $no-cols = 1]">
    <tr>
    <xsl:for-each select=". | following-sibling::person[position()
    &lt; $no-cols]">
    <td>
    <xsl:value-of select="name"/>
    <br/>
    <xsl:text>more info: </xsl:text>
    <xsl:value-of select="funktion"/>
    </td>
    </xsl:for-each>
    </tr>
    </xsl:for-each>
    </table>
    </body>
    </html>
    </xsl:template>

    </xsl:stylesheet>
    == end of XSL2 ==========================

    If your XML doesn't look like that then the XSL code might need changing -
    but as you haven't posted any example XML that's something you will have to
    figure.

    The code will also need to be drastically different if you are sorting the
    data as it is placed into the table - because axes work on the original
    order of the nodes in the input document rather than the sorted node-set.

    Cheers
    Marrow


    "Peter Rohleder" <> wrote in message
    news:...
    > Hi Marrow,
    >
    > you write:
    >
    > (...)
    > > Perhaps if you post some example XML and describe what you are actually
    > > trying to achieve? It is difficult to see what the problem might be

    from
    > > just an incomplete fragment of XSLT code.
    > >
    > > I suspect you might be wanting to organize things into a table with a

    fixed
    > > 3 coulumns?

    >
    > yes, thats true!
    >
    > I solved the problem by replacing following part, which doesn't work:
    >
    > >>
    > >> <!-- Part 4 doens'nt work-->
    > >> <xsl:call-template name="handlePerson">
    > >> <xsl:with-param name="persondata"
    > >> select="following-sibling::*[1]"/>
    > >> </xsl:call-template>

    >
    > (...)
    >
    > by(new code):
    > -----------
    > <xsl:for-each select="following-sibling::*">
    > <xsl:if test="position() &lt; 3">
    >
    > <td>
    > <xsl:call-template name="handlePerson">
    > <xsl:with-param name="persondata" select="."/> </xsl:call-template>
    > </td>
    >
    > </xsl:if>
    > </xsl:for-each>
    > -----------
    >
    > Now it works, but i still have no idea why the code above doesn't work
    > and the new code works.
    >
    > Thanks for your response.
    >
    > Peter Rohleder
    >
    >
    >
     
    Marrow, Jun 28, 2003
    #3
  4. Peter Rohleder <> writes:

    > I solved the problem by replacing following part, which doesn't work:
    >
    > >>
    > >> <!-- Part 4 doens'nt work-->
    > >> <xsl:call-template name="handlePerson">
    > >> <xsl:with-param name="persondata"
    > >> select="following-sibling::*[1]"/>
    > >> </xsl:call-template>

    >
    > (...)
    >
    > by(new code):
    > -----------
    > <xsl:for-each select="following-sibling::*">
    > <xsl:if test="position() &lt; 3">
    >
    > <td>
    > <xsl:call-template name="handlePerson">
    > <xsl:with-param name="persondata" select="."/>
    > </xsl:call-template>
    > </td>
    >
    > </xsl:if>
    > </xsl:for-each>
    > -----------
    >
    > Now it works, but i still have no idea why the code above doesn't work
    > and the new code works.


    It's hard to know for sure, since your original example was
    fragmentary, but this sure looks like it may be a problem in the
    template you are calling. When you pass in a node under the
    name 'persondata', you have access in the template to two
    conceptually distinct nodes: (1) the $persondata node, and (2)
    the current node. If I had to guess, I'd suspect that the
    template 'handlePerson' habitually refers to the current node
    (i.e. '.') where it should refer to $persondata. Since in some
    cases (the calls that work) the two nodes are identical, it
    works sometimes, and makes the problem look as if it's a problem
    in the call, rather than a problem in the template.

    I hope this helps.

    -C. M. Sperberg-McQueen
    World Wide Web Consortium
     
    C. M. Sperberg-McQueen, Jul 2, 2003
    #4
    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. Kathy Burke
    Replies:
    0
    Views:
    699
    Kathy Burke
    Aug 3, 2003
  2. Niall Smart
    Replies:
    1
    Views:
    1,827
    Dimitre Novatchev [MVP XML]
    Mar 5, 2004
  3. Petterson Mikael

    test of following-sibling[2] does not work

    Petterson Mikael, Feb 6, 2006, in forum: XML
    Replies:
    1
    Views:
    865
    George Bina
    Feb 6, 2006
  4. kmartin7
    Replies:
    0
    Views:
    1,394
    kmartin7
    Aug 2, 2006
  5. Replies:
    3
    Views:
    6,946
Loading...

Share This Page