[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

RE: xslt: Wrapping multiple elements in a parent eleme

Subject: RE: xslt: Wrapping multiple elements in a parent element
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Fri, 09 May 2003 12:48:05 -0400
xslt match multiple
Hi Steve,

As for your question, it was a bit unclear (especially as to the structure of your source), but it sounds like a variant of a grouping problem. Hint: try looking at keys to associate elements that you want to group with another "key" element; when that element is processed, a wrapper can be created and the group processed.

I dunno if Sundar's code will do it for you (I hope so!); in any case, I thought his solution was worth looking at as an exercise:

<?xml version="1.0"?>
<Root>
        <a>
                <b>
                        <c>
                        <d>sundar</d>
                        <e>
                                <f>fff</f>
                        </e>
                        </c>
                        <d>sundar2</d>
                </b>
        </a>
        <a>
                <b>
                        <d>sundar3</d>
                </b>
        </a>
        <d>sundar4</d>
</Root>

I am trying to group all the <d> elements separately and rest of the
document will be same.
<d> elements will be grouped under <D> element.

This is the stylesheet which does that:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="yes" />

<xsl:template match="/Root">
<Root>
        <xsl:apply-templates select="*[name(.)!='d']"/>
        <D>
        <xsl:apply-templates select="//d"/>
        </D>
</Root>
</xsl:template>

<xsl:template match="*">
        <xsl:element name="{name(.)}">
                <xsl:value-of select="text()"/>
        <xsl:apply-templates select="*[name(.)!='d']"/>
        </xsl:element>
</xsl:template>

<xsl:template match="d">
        <d>
                <xsl:value-of select="text()"/>
        </d>
</xsl:template>

</xsl:stylesheet>

An alternative (accomplishes exactly the same thing):


<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="yes" />

<xsl:template match="/Root">
  <Root>
    <xsl:apply-templates/>
    <D>
      <xsl:apply-templates mode="dMode"/>
    </D>
  </Root>
</xsl:template>

<xsl:template match="*">
  <!-- copies elements in default traversal -->
  <xsl:copy>
    <xsl:apply-templates/>
  </xsl:copy>
</xsl:template>

<xsl:template match="d"/>
<!-- suppresses d element in default traversal -->

<xsl:template match="d" mode="dMode">
  <!-- in dMode, we copy the d -->
  <xsl:copy-of select=".">
</xsl:template>

<xsl:template match="text()" mode="dMode"/>
<!-- when in dMode, we want to suppress everything else;
     this accomplishes that by suppressing the text nodes -->

</xsl:stylesheet>

The differences between the "pull" (Sundar's) and this "push" stylesheet are instructive. Although they create the same output, there are differences for maintenance and extensibility. Many will prefer the "pull" approach since it doesn't rely on the built-in default templates, so is easier to read and understand. (For newbies, let's add them here, at least as they apply to this stylesheet:

<xsl:template match="*">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="text()">
  <xsl:value-of select="."/>
</xsl:template>

<xsl:template match="*" mode="dMode">
  <xsl:apply-templates mode="dMode"/>
</xsl:template>

If you don't know those templates are working, my stylesheet becomes pretty mysterious!)

On the other hand, the "push" approach I used has certain attractions. Where the pull approach works by deliberately "stepping around" the <d> elements where they would be selected, this lets them get matched to templates which happen to do nothing with them, then lets a different tree traversal (in a different mode) go through and copy them into the new wrapper. This general pattern may scale better to complex transformation requirements (you might do this to create endnotes to a publication, for example), though for a one-off it will hardly matter.

One functional difference between the stylesheets is that if you ever had <d> elements wrapped inside other <d> elements, my stylesheet would preserve this wrapping in their copies, where Sundar's would split them out. Probably an academic point (and mine could be easily tweaked to split them out).

Which one you "should" prefer depends totally on how this stylesheet is being used and maintained.

Cheers (and thanks to Sundar) --
Wendell


___&&__&_&___&_&__&&&__&_&__&__&&____&&_&___&__&_&&_____&__&__&&_____&_&&_ "Thus I make my own use of the telegraph, without consulting the directors, like the sparrows, which I perceive use it extensively for a perch." -- Thoreau


XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list



Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.