Ragulf,
This is actually not a straightforward flattening, though it may appear to be.
The trick is that you not only need to flatten, you also need to group.
Some subnode elements here (the one that have mynode children, not content)
will disappear in the flattening, while the others (those with content)
will be promoted -- but the latter have to be grouped, with siblings, but
not with all siblings, just with those up to the next subnode with a mynode
child.
So one hierarchy has to be interpolated while another is removed!
(Note how much easier it would be if you could just leave all
mynode[(_at_)name='xxx'] nodes together, rather than leave all subnodes in their
current order.)
For this kind of problem in XSLT 1.0 there are two tried-and-true methods:
key-based grouping by "leader" nodes (an adaptation of Muenchian positional
grouping), and the fun "tree visitor" or "forward stepping" technique,
whereby you explicitly walk the tree forward one node at a time, copying
them until you hit one that ends the group.
I have used the latter approach, below.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="//subnode[not(mynode)]"/>
<!-- Reach down and grab all the subnodes that are candidates
for promotion. -->
</xsl:template>
<xsl:template match="subnode">
<xsl:choose>
<!-- This is implemented as a 'choose' for clarity: you could have
done the filtering in the 'select'. -->
<xsl:when test="preceding-sibling::subnode[1][not(mynode)]"/>
<!-- When there's an immediately preceding subnode sibling without
a mynode child, we're already accounted for, so we're
suppressed. -->
<xsl:otherwise>
<xsl:variable name="lead-subnode" select="."/>
<xsl:for-each select="ancestor::mynode[1]">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="$lead-subnode" mode="tuck"/>
<!-- Here we kick off the 'forward step' explicit recursion -->
</xsl:copy>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="subnode" mode="tuck">
<xsl:copy-of select="."/>
<xsl:apply-templates select="following-sibling::subnode[1]" mode="tuck"/>
<!-- Step forward to the next sibling if there is one. -->
</xsl:template>
<xsl:template match="subnode[mynode]" mode="tuck"/>
<!-- When this template is matched, we're done tucking for now. -->
Cheers,
Wendell
At 09:56 AM 1/19/2005, you wrote:
Hi, I have a hierarchic structure, that I would like to flatten.
I have tried looking for some examples, but I have not been able to expand
the examples I have found, so that they will work on my problem.
(I have no influence on either input or output format, which is simplified
here)
Regards,
Ragulf Pickaxe :-)
Expanding on the example from David Pawson's site:
http://www.dpawson.co.uk/xsl/sect2/flatten.html
I have the following XML and would like to generate the flat structure as
shown:
Input XML:
<mynode name="xxx">
<subnode>Some text</subnode>
<subnode>
<mynode name="yyy">
<subnode><b>Some bold text</b></subnode>
<subnode>Some text where some of it is <b>bold text</b></subnode>
<subnode>
<mynode name="zzz">
<subnode>Some text</subnode>
<subnode>Some text</subnode>
</mynode>
</subnode>
<subnode>Yet some text</subnode>
</mynode>
</subnode>
<subnode>Some more text, <i>italic</i> is some of it</subnode>
</mynode>
Output XML:
<mynode name="xxx">
<subnode>Some text</subnode>
<mynode name="yyy">
<subnode><b>Some bold text</b></subnode>
<subnode>Some text where some of it is <b>bold text</b></subnode>
</mynode>
<mynode name="zzz">
<subnode>Some text</subnode>
<subnode>Some text</subnode>
</mynode>
<mynode name="yyy">
<subnode>Yet some text</subnode>
</mynode>
<mynode name="xxx">
<subnode>Some more text, <i>italic</i> is some of it</subnode>
</mynode>
I have tried some various forms of modes, and such, but alas no success,
and no idea how to obtain success. The problem is with retaining the
subnode under mynode structure, while also having the subnodes in the same
document order as in the input.
_________________________________________________________________
FREE pop-up blocking with the new MSN Toolbar - get it now!
http://toolbar.msn.click-url.com/go/onm00200415ave/direct/01/
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--
___&&__&_&___&_&__&&&__&_&__&__&&____&&_&___&__&_&&_____&__&__&&_____&_&&_
"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
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--