|
[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: Flattening hierarchic xml, retaining some structur
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[@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. ___&&__&_&___&_&__&&&__&_&__&__&&____&&_&___&__&_&&_____&__&__&&_____&_&&_ "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
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|

Cart








