Use apply-templates selectively in XSLT

Discussion in 'XML' started by abhishek.smu@gmail.com, Feb 23, 2007.

  1. Guest

    Given an XML like:

    <root>
    <node>8</node>
    <node>21</node>
    <node>-7</node>
    <node>13</node>
    <node>43</node>
    <node>2</node>
    </root>


    how might I select only the 2nd, 3rd and 4th nodes (or more
    generically, any selective set of nodes like first 4, last 3, every
    other node etc)? Note that since my XSLT obviously won't know the
    value inside a node, I can't just pick a node with the values of 21,
    -7 and 13 using xsl:if or something like it. I tried playing around
    with some things like for-each and creating a template with some sort
    of a recursive scenario, but to no avail.


    Any help is appreciated.


    Thanks


    Abhishek
     
    , Feb 23, 2007
    #1
    1. Advertising

  2. wrote:
    > how might I select only the 2nd, 3rd and 4th nodes


    Write a select expression that tests position().

    --
    Joe Kesselman / Beware the fury of a patient man. -- John Dryden
     
    Joseph Kesselman, Feb 23, 2007
    #2
    1. Advertising

  3. roy axenov Guest

    On Feb 23, 7:51 pm, ""
    <> wrote:
    > <root>
    > <node>8</node>
    > <node>21</node>
    > <node>-7</node>
    > <node>13</node>
    > <node>43</node>
    > <node>2</node>
    > </root>
    >
    > how might I select only the 2nd, 3rd and 4th nodes


    <xsl:template match="node"/>
    <xsl:template
    match="node[position() &gt; 1 and position() &lt; 5]">
    <xsl:copy><xsl:apply-templates/></xsl:copy>
    </xsl:template>

    > (or more generically, any selective set of nodes like
    > first 4,


    <xsl:template match="node"/>
    <xsl:template
    match="node[count(preceding-sibling::node) &lt; 4]">
    <xsl:copy><xsl:apply-templates/></xsl:copy>
    </xsl:template>

    > last 3,


    <xsl:template match="node"/>
    <xsl:template
    match="node[count(following-sibling::node) &lt; 3]">
    <xsl:copy><xsl:apply-templates/></xsl:copy>
    </xsl:template>

    > every other node


    <xsl:template match="node"/>
    <xsl:template
    match="node[position() mod 2=0]">
    <xsl:copy><xsl:apply-templates/></xsl:copy>
    </xsl:template>

    Note that depending on what exactly you are trying to do,
    it might be a good idea to use xsl:key/key() combo together
    with selecting the nodesets you need instead of
    template-based matching of the nodes you need processed.

    > Note that since my XSLT obviously won't know the value
    > inside a node


    I beg your pardon? Of course it will. Use string() or just
    '.'. Note that this is a bit esoteric and often not a very
    good practice if you stop and think about it for a moment.
    Anyway, processing based on a value of the node is
    definitely possible.

    > I can't just pick a node with the values of 21, -7 and 13


    Of course you can.

    <xsl:template match="node"/>
    <xsl:template
    match="node[.=21 or .=-7 or .=13]">
    <xsl:copy><xsl:apply-templates/></xsl:copy>
    </xsl:template>

    Or did you mean that your problem requires matching of
    nodes based on their position in the document, not on the
    plain data they contain? If that is the case, the solutions
    are described above.

    Another thing to keep in mind is that if you're processing
    a homogeneous nodeset using node position to switch
    processing modes, it is often an indicator of poor XML
    design of your source document; but whatever suits you.

    > using xsl:if or something like it. I tried playing around
    > with some things like for-each


    As a rule of the thumb, if and choose should be replaced
    with predicate-based selection and matching where possible.
    Where impossible, go ahead and use if or choose, but
    remember that it's a good idea to feel somewhat dirty and
    uncomfortable afterwards.

    You should also realize that for-each is very different
    from what you would expect out of similarly based language
    constructs or library methods in imperative languages such
    as Perl, PHP, C++ or Java. Use template-based processing
    instead.

    > and creating a template with some sort of a recursive
    > scenario, but to no avail.


    I'm not sure I can see how recursive processing would be
    helpful in this particular case.

    --
    roy axenov
     
    roy axenov, Feb 23, 2007
    #3
  4. Guest

    On Feb 23, 2:03 pm, "roy axenov" <> wrote:
    > On Feb 23, 7:51 pm, ""
    >
    > <> wrote:
    > > <root>
    > > <node>8</node>
    > > <node>21</node>
    > > <node>-7</node>
    > > <node>13</node>
    > > <node>43</node>
    > > <node>2</node>
    > > </root>

    >
    > > how might I select only the 2nd, 3rd and 4th nodes

    >
    > <xsl:template match="node"/>
    > <xsl:template
    > match="node[position() &gt; 1 and position() &lt; 5]">
    > <xsl:copy><xsl:apply-templates/></xsl:copy>
    > </xsl:template>
    >
    > > (or more generically, any selective set of nodes like
    > > first 4,

    >
    > <xsl:template match="node"/>
    > <xsl:template
    > match="node[count(preceding-sibling::node) &lt; 4]">
    > <xsl:copy><xsl:apply-templates/></xsl:copy>
    > </xsl:template>
    >
    > > last 3,

    >
    > <xsl:template match="node"/>
    > <xsl:template
    > match="node[count(following-sibling::node) &lt; 3]">
    > <xsl:copy><xsl:apply-templates/></xsl:copy>
    > </xsl:template>
    >
    > > every other node

    >
    > <xsl:template match="node"/>
    > <xsl:template
    > match="node[position() mod 2=0]">
    > <xsl:copy><xsl:apply-templates/></xsl:copy>
    > </xsl:template>
    >
    > Note that depending on what exactly you are trying to do,
    > it might be a good idea to use xsl:key/key() combo together
    > with selecting the nodesets you need instead of
    > template-based matching of the nodes you need processed.
    >
    > > Note that since my XSLT obviously won't know the value
    > > inside a node

    >
    > I beg your pardon? Of course it will. Use string() or just
    > '.'. Note that this is a bit esoteric and often not a very
    > good practice if you stop and think about it for a moment.
    > Anyway, processing based on a value of the node is
    > definitely possible.
    >
    > > I can't just pick a node with the values of 21, -7 and 13

    >
    > Of course you can.
    >
    > <xsl:template match="node"/>
    > <xsl:template
    > match="node[.=21 or .=-7 or .=13]">
    > <xsl:copy><xsl:apply-templates/></xsl:copy>
    > </xsl:template>
    >
    > Or did you mean that your problem requires matching of
    > nodes based on their position in the document, not on the
    > plain data they contain? If that is the case, the solutions
    > are described above.
    >
    > Another thing to keep in mind is that if you're processing
    > a homogeneous nodeset using node position to switch
    > processing modes, it is often an indicator of poor XML
    > design of your source document; but whatever suits you.
    >
    > > using xsl:if or something like it. I tried playing around
    > > with some things like for-each

    >
    > As a rule of the thumb, if and choose should be replaced
    > with predicate-based selection and matching where possible.
    > Where impossible, go ahead and use if or choose, but
    > remember that it's a good idea to feel somewhat dirty and
    > uncomfortable afterwards.
    >
    > You should also realize that for-each is very different
    > from what you would expect out of similarly based language
    > constructs or library methods in imperative languages such
    > as Perl, PHP, C++ or Java. Use template-based processing
    > instead.
    >
    > > and creating a template with some sort of a recursive
    > > scenario, but to no avail.

    >
    > I'm not sure I can see how recursive processing would be
    > helpful in this particular case.
    >
    > --
    > roy axenov


    WOW !!!

    Thank you so much. Since I am a beginner at this, I had never even
    heard of the node and position things. This is absolute magic to me.

    And yes, I did mean that my "problem requires matching of nodes based
    on their position in the document, not on the plain data they
    contain."

    Once again, thanks a lot.

    Abhishek
     
    , Feb 24, 2007
    #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. Stefan Siegl
    Replies:
    1
    Views:
    964
    Marrow
    Jul 18, 2003
  2. Cyrille \cns\ Szymanski

    xsl apply-templates select=not(...)

    Cyrille \cns\ Szymanski, Nov 7, 2003, in forum: XML
    Replies:
    4
    Views:
    597
    Cyrille \cns\ Szymanski
    Nov 11, 2003
  3. Vijay singh
    Replies:
    1
    Views:
    436
    Martin Honnen
    Nov 4, 2004
  4. JKop
    Replies:
    3
    Views:
    479
  5. recover
    Replies:
    2
    Views:
    812
    recover
    Jul 25, 2006
Loading...

Share This Page