Combining XML elements with XSL

Discussion in 'XML' started by mikea_59, Feb 15, 2005.

  1. mikea_59

    mikea_59 Guest

    I am having trouble combining similar elements. Elements can be
    combined if they have the same name and the same attribute values. I
    can handle single level elements but am having problems with
    multi-level elments (level of element nesting is unbound). I cannot
    rely on fixed element names in the translator code since the translator
    will be general purpose, elements names are not fixed.

    Example input

    <test>
    <A x="0">
    <B>1</B>
    </A>
    <A x="0">
    <C>2</C>
    </A>
    <A x="0">
    <D x="0">
    <E>3</E>
    </D>
    </A>
    <A x="0">
    <D x="0">
    <E>3</E>
    </D>
    </A>
    <A x="0">
    <D x="1">
    <E>5</E>
    </D>
    </A>
    <A x="1">
    <B>4</B>
    </A>
    </test>

    example output:

    <test>
    <A x="0">
    <B>1</B>
    <C>2</C>
    <D x="0">
    <E>3</E>
    </D>
    <D x="1">
    <E>5</E>
    </D>
    </A>
    <A x="1">
    <B>4</B>
    </A>
    </test>

    Any help would be greatly appreciated - still an XSL newbie
     
    mikea_59, Feb 15, 2005
    #1
    1. Advertising

  2. mikea_59

    Joris Gillis Guest

    On 15 Feb 2005 13:50:10 -0800, mikea_59 <> wrote:

    > I am having trouble combining similar elements. Elements can be
    > combined if they have the same name and the same attribute values. I
    > can handle single level elements but am having problems with
    > multi-level elments (level of element nesting is unbound). I cannot
    > rely on fixed element names in the translator code since the translator
    > will be general purpose, elements names are not fixed.

    Hi,

    I'm afraid you'll have to use an 'xx:node-set' extension function to solve
    this (in XSLT1.0).

    Here's one solution (tested with Saxon), gives correct output for your
    input.


    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0" xmlns:exsl="http://exslt.org/common"
    extension-element-prefixes="exsl">

    <xsl:eek:utput method="xml" indent="yes"/>

    <xsl:strip-space elements="*"/>
    <xsl:key name="element" match="*" use="concat(local-name(),@*)"/>

    <xsl:template match="*">
    <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:variable name="set">
    <xsl:copy-of select="key('element',concat(local-name(),@*))/*"/>
    </xsl:variable>
    <xsl:apply-templates select="text()"/>
    <xsl:apply-templates
    select="exsl:node-set($set)/*[generate-id()=generate-id(key('element',concat(local-name(),@*)))]"/>
    </xsl:copy>
    </xsl:template>

    </xsl:stylesheet>

    regards,
    Joris Gillis
    --
    Using Opera's revolutionary e-mail client: http://www.opera.com/m2/
     
    Joris Gillis, Feb 17, 2005
    #2
    1. Advertising

  3. mikea_59

    mikea_59 Guest

    That worked - thanks a lot! What a great NG.

    So, is this strictly a 1.0 solution? Doesn't 2.0 eliminate the need
    to use node-set() by enabling temporary templates? Is node-set() even
    available in 2.0 - in Saxon? How would I change this for 2.0?

    Sorry for all the ???

    Thanks again
    mikea
     
    mikea_59, Feb 17, 2005
    #3
  4. mikea_59

    Joris Gillis Guest

    On 17 Feb 2005 11:56:09 -0800, mikea_59 <> wrote:

    > So, is this strictly a 1.0 solution?

    Everything that can be achieved in XSLT1.0 certainly can in XSLT2.0, isn't
    that logic;)

    > Doesn't 2.0 eliminate the need
    > to use node-set() by enabling temporary templates?

    Excerpt form the latest XSLT2.0 working draft:
    "The result tree fragment data-type is eliminated. A variable-binding
    element with content (and no as attribute) now constructs a temporary
    tree, and the value of the variable is the root node of this tree (see 9.3
    Values of Variables and Parameters). With an as attribute, a
    variable-binding element may be used to construct an arbitrary sequence.
    These features eliminate the need for the xx:node-set extension function
    provided by many XSLT 1.0 implementations."

    > available in 2.0 - in Saxon? How would I change this for 2.0?


    I don't have experience with 2.0, but I guess writing '$set' in stead of
    'exsl:node-set($set)' will do...


    regards,
    Joris Gillis
    --
    Using Opera's revolutionary e-mail client: http://www.opera.com/m2/
     
    Joris Gillis, Feb 17, 2005
    #4
  5. mikea_59

    mikea_59 Guest

    Joris Gillis wrote:
    > On 17 Feb 2005 11:56:09 -0800, mikea_59 <> wrote:
    >
    > > So, is this strictly a 1.0 solution?

    > Everything that can be achieved in XSLT1.0 certainly can in XSLT2.0,

    isn't
    > that logic;)


    Yes, very logical, but when I set stylesheet to version=2.0 and
    re-run the translation in Saxon, I get an error:

    "A sequence of more than one item is not allowed as the first
    argument of generate-id()"

    I guess it's not related to node-set()

    >
    > > Doesn't 2.0 eliminate the need
    > > to use node-set() by enabling temporary templates?

    > Excerpt form the latest XSLT2.0 working draft:
    > "The result tree fragment data-type is eliminated. A variable-binding


    > element with content (and no as attribute) now constructs a temporary


    > tree, and the value of the variable is the root node of this tree

    (see 9.3
    > Values of Variables and Parameters). With an as attribute, a
    > variable-binding element may be used to construct an arbitrary

    sequence.
    > These features eliminate the need for the xx:node-set extension

    function
    > provided by many XSLT 1.0 implementations."
    >
    > > available in 2.0 - in Saxon? How would I change this for 2.0?

    >
    > I don't have experience with 2.0, but I guess writing '$set' in stead

    of
    > 'exsl:node-set($set)' will do...
    >
    >
    > regards,
    > Joris Gillis
    > --
    > Using Opera's revolutionary e-mail client: http://www.opera.com/m2/
     
    mikea_59, Feb 17, 2005
    #5
  6. mikea_59

    Joris Gillis Guest

    On 17 Feb 2005 13:21:49 -0800, mikea_59 <> wrote:

    > "A sequence of more than one item is not allowed as the first
    > argument of generate-id()"


    Really? Then they have changed the behaviour of generate-id().

    Solution:
    change
    <xsl:apply-templates
    select="exsl:node-set($set)/*[generate-id()=generate-id(key('element',concat(local-name(),@*)))]"/>
    into
    <xsl:apply-templates
    select="exsl:node-set($set)/*[generate-id()=generate-id(key('element',concat(local-name(),@*))[1])]"/>

    --
    Using Opera's revolutionary e-mail client: http://www.opera.com/m2/
     
    Joris Gillis, Feb 17, 2005
    #6

  7. > Really? Then they have changed the behaviour of generate-id().


    it's a more or less pervasive change, as part of the stricter tying
    introduced in 2 most instances of functions that expect a single node
    complain if given more than one node rather than silently taking the
    first in doc order.

    David
     
    David Carlisle, Feb 17, 2005
    #7
  8. mikea_59

    mikea_59 Guest

    It looks like that did the trick, thanks a lot. I'm still not sure I
    follow the syntax of the select attribute, I guess I'll go back to my
    Kay book...

    Thanks again,
    mikea
     
    mikea_59, Feb 17, 2005
    #8
  9. mikea_59

    Joris Gillis Guest

    Tempore 23:15:45, die Thursday 17 February 2005 AD, hinc in foro {comp.text.xml} scripsit mikea_59 <>:

    >
    > It looks like that did the trick, thanks a lot. I'm still not sure I
    > follow the syntax of the select attribute


    you mean this line?

    <xsl:apply-templates select="$set/*[generate-id()=generate-id(key('element',concat(local-
    name(),@*))[1])]"/>

    well, the trick is to let the xslt processor create a key lookup table based on the node-set in the variable in stead of a lookup table indexing all nodes in the input XML document.

    The 'generate-id()' + 'key()' stuff is just basic Muenchian grouping technique...

    --
    Joris Gillis (http://www.ticalc.org/cgi-bin/acct-view.cgi?userid=38041)
    "Φιλήκοον ειναι μαλλον η ÆιλÌλαλον" - ΚλεÌβοÅλοÂ
     
    Joris Gillis, Feb 17, 2005
    #9
    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. Peter Flynn
    Replies:
    0
    Views:
    394
    Peter Flynn
    Apr 11, 2004
  2. Replies:
    1
    Views:
    3,687
    A. Bolmarcich
    May 27, 2005
  3. Rob Smegma
    Replies:
    1
    Views:
    1,844
    shaun
    Sep 26, 2005
  4. Paul
    Replies:
    5
    Views:
    143
    Peter Szinek
    Apr 13, 2007
  5. gregarican

    Combining Array Elements

    gregarican, Aug 24, 2007, in forum: Ruby
    Replies:
    12
    Views:
    173
    Phrogz
    Sep 10, 2007
Loading...

Share This Page