Combining XML elements with XSL

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • mikea_59

    Combining XML elements with XSL

    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

  • Joris Gillis

    #2
    Re: Combining XML elements with XSL

    On 15 Feb 2005 13:50:10 -0800, mikea_59 <mikea_59@yahoo .com> wrote:
    [color=blue]
    > 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.[/color]
    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:styleshe et xmlns:xsl="http ://www.w3.org/1999/XSL/Transform"
    version="1.0" xmlns:exsl="htt p://exslt.org/common"
    extension-element-prefixes="exsl" >

    <xsl:output method="xml" indent="yes"/>

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

    <xsl:template match="*">
    <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:variable name="set">
    <xsl:copy-of select="key('el ement',concat(l ocal-name(),@*))/*"/>
    </xsl:variable>
    <xsl:apply-templates select="text()"/>
    <xsl:apply-templates
    select="exsl:no de-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/

    Comment

    • mikea_59

      #3
      Re: Combining XML elements with XSL


      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

      Comment

      • Joris Gillis

        #4
        Re: Combining XML elements with XSL

        On 17 Feb 2005 11:56:09 -0800, mikea_59 <mikea_59@yahoo .com> wrote:
        [color=blue]
        > So, is this strictly a 1.0 solution?[/color]
        Everything that can be achieved in XSLT1.0 certainly can in XSLT2.0, isn't
        that logic;)
        [color=blue]
        > Doesn't 2.0 eliminate the need
        > to use node-set() by enabling temporary templates?[/color]
        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 ."
        [color=blue]
        > available in 2.0 - in Saxon? How would I change this for 2.0?[/color]

        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/

        Comment

        • mikea_59

          #5
          Re: Combining XML elements with XSL


          Joris Gillis wrote:[color=blue]
          > On 17 Feb 2005 11:56:09 -0800, mikea_59 <mikea_59@yahoo .com> wrote:
          >[color=green]
          > > So, is this strictly a 1.0 solution?[/color]
          > Everything that can be achieved in XSLT1.0 certainly can in XSLT2.0,[/color]
          isn't[color=blue]
          > that logic;)[/color]

          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()
          [color=blue]
          >[color=green]
          > > Doesn't 2.0 eliminate the need
          > > to use node-set() by enabling temporary templates?[/color]
          > Excerpt form the latest XSLT2.0 working draft:
          > "The result tree fragment data-type is eliminated. A variable-binding[/color]
          [color=blue]
          > element with content (and no as attribute) now constructs a temporary[/color]
          [color=blue]
          > tree, and the value of the variable is the root node of this tree[/color]
          (see 9.3[color=blue]
          > Values of Variables and Parameters). With an as attribute, a
          > variable-binding element may be used to construct an arbitrary[/color]
          sequence.[color=blue]
          > These features eliminate the need for the xx:node-set extension[/color]
          function[color=blue]
          > provided by many XSLT 1.0 implementations ."
          >[color=green]
          > > available in 2.0 - in Saxon? How would I change this for 2.0?[/color]
          >
          > I don't have experience with 2.0, but I guess writing '$set' in stead[/color]
          of[color=blue]
          > 'exsl:node-set($set)' will do...
          >
          >
          > regards,
          > Joris Gillis
          > --
          > Using Opera's revolutionary e-mail client: http://www.opera.com/m2/[/color]

          Comment

          • Joris Gillis

            #6
            Re: Combining XML elements with XSL

            On 17 Feb 2005 13:21:49 -0800, mikea_59 <mikea_59@yahoo .com> wrote:
            [color=blue]
            > "A sequence of more than one item is not allowed as the first
            > argument of generate-id()"[/color]

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

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

            --
            Using Opera's revolutionary e-mail client: http://www.opera.com/m2/

            Comment

            • David Carlisle

              #7
              Re: Combining XML elements with XSL

              [color=blue]
              > Really? Then they have changed the behaviour of generate-id().[/color]

              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

              Comment

              • mikea_59

                #8
                Re: Combining XML elements with XSL


                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

                Comment

                • Joris Gillis

                  #9
                  Re: Combining XML elements with XSL

                  Tempore 23:15:45, die Thursday 17 February 2005 AD, hinc in foro {comp.text.xml} scripsit mikea_59 <mikea_59@yahoo .com>:
                  [color=blue]
                  >
                  > It looks like that did the trick, thanks a lot. I'm still not sure I
                  > follow the syntax of the select attribute[/color]

                  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-v...i?userid=38041)
                  "ΦιλÎ ®ÎºÎ¿Î¿à ŽÂ½ εινΠ±ÃŽÂ¹ μαλΠ»ÃŽÂ¿ÃŽÂ½ η φιλόΠ»ÃŽÂ±ÃŽÂ»ÃŽÂ¿ÃŽ ½" - Κλεϊ’βουà ŽÂ»ÃŽÂ¿Ãâ€š

                  Comment

                  Working...