XSLT: Perform an action once per element type?

Discussion in 'XML' started by Stuart A Yeates, Aug 20, 2003.

  1. I'm trying to write a template that matches "*" but which has an if
    clause which if only executed once per type of element seen (where
    all elements of a type have the same name and namespace). The test
    in the example below doesn't work, but it seems that there must be
    some relatively simple text i'm overlooking.

    <!--
    - process an element
    -->
    <xsl:template match="*">
    <xsl:copy>
    <xsl:if test="last()=position()">
    <xsl:text>
    i occur once for each type of element. this time it's for:
    </xsl:text>
    <xsl:value-of select="."/>
    </xsl:if>
    <xsl:apply-templates/>
    </xsl:copy>
    </xsl:template>

    If my input is:

    <a>
    <b> <d/><d/> </b>
    <c> <d/><b/> </c>
    </a>

    I want instantiate the body of my if once for <a>, once for <b>,
    once for <c> and once for <e>. It doesn't really bother me what
    order they happen it.

    I suspect that what I need is a recursive template that finds
    determines whether the current element occupies some special
    place (first or last), but i'm not sure how to write it.

    stuart
    --
    -- stuart yeates <> aka `loam'
    Sufficiently advanced political correctness is indistinguishable
    from irony.
    X-no-archive:yes
    Stuart A Yeates, Aug 20, 2003
    #1
    1. Advertising

  2. Re: Perform an action once per element type?

    Use:

    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:eek:utput omit-xml-declaration="yes"/>

    <xsl:key name="kName" match="*" use="name()"/>

    <xsl:template match="*[generate-id()
    = generate-id(key('kName',
    name()
    )[1]
    )
    ]">
    Element name: <xsl:value-of select="name()"/>
    <xsl:apply-templates/>
    </xsl:template>
    <xsl:template match="node()[not(self::*)]"/>
    </xsl:stylesheet>

    This transformation, when applied on your source.xml:

    <a>
    <b>
    <d/>
    <d/>
    </b>
    <c>
    <d/>
    <b/>
    </c>
    </a>

    produces the desired result:


    Element name: a
    Element name: b
    Element name: d
    Element name: c


    Read about the "Muenchian method for grouping" in order to understand what
    actually happens here.



    =====
    Cheers,

    Dimitre Novatchev.
    http://fxsl.sourceforge.net/ -- the home of FXSL

    "Stuart A Yeates" <> wrote in message
    news:...
    > I'm trying to write a template that matches "*" but which has an if
    > clause which if only executed once per type of element seen (where
    > all elements of a type have the same name and namespace). The test
    > in the example below doesn't work, but it seems that there must be
    > some relatively simple text i'm overlooking.
    >
    > <!--
    > - process an element
    > -->
    > <xsl:template match="*">
    > <xsl:copy>
    > <xsl:if test="last()=position()">
    > <xsl:text>
    > i occur once for each type of element. this time it's for:
    > </xsl:text>
    > <xsl:value-of select="."/>
    > </xsl:if>
    > <xsl:apply-templates/>
    > </xsl:copy>
    > </xsl:template>
    >
    > If my input is:
    >
    > <a>
    > <b> <d/><d/> </b>
    > <c> <d/><b/> </c>
    > </a>
    >
    > I want instantiate the body of my if once for <a>, once for <b>,
    > once for <c> and once for <e>. It doesn't really bother me what
    > order they happen it.
    >
    > I suspect that what I need is a recursive template that finds
    > determines whether the current element occupies some special
    > place (first or last), but i'm not sure how to write it.
    >
    > stuart
    > --
    > -- stuart yeates <> aka `loam'
    > Sufficiently advanced political correctness is indistinguishable
    > from irony.
    > X-no-archive:yes
    Dimitre Novatchev, Aug 20, 2003
    #2
    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. CoX
    Replies:
    3
    Views:
    467
  2. Replies:
    2
    Views:
    2,849
    Toby Inkster
    Aug 15, 2004
  3. Benton
    Replies:
    10
    Views:
    694
    kferron
    Dec 5, 2006
  4. mike
    Replies:
    3
    Views:
    372
  5. Replies:
    4
    Views:
    231
Loading...

Share This Page