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

Maximum "child-depth" of current node?

Subject: Maximum "child-depth" of current node?
From: "Scott Trenda" <Scott.Trenda@xxxxxxxx>
Date: Tue, 16 Oct 2007 10:31:02 -0500
 Maximum "child-depth" of current node?
Hey XSL-List. Got a bugger of a problem that started to drive me nuts
yesterday, figured I'd ask here first thing today to avoid pulling my
hair out over this. :P

I just found out yesterday that the nest-hierarchy system I set up for a
recent big project has to essentially be done in _reverse_ for a
different format, but this one isn't as simple. I'm basically making a
list header hierarchy into a nested HTML table header in one format, and
I have to make it into similar-looking CSV in the other format. Take
this example data:

<x>
  <c>col1</c>
  <c>col2</c>
  <g n='grp1'>
    <c>col3</c>
    <c>col4</c>
    <c>col5</c>
  </g>
  <g n='grp2'>
    <c>col6</c>
    <g n='grp3'>
      <c>col7</c>
      <c>col8</c>
    </g>
    <c>col9</c>
  </g>
  <c>col10</c>
  <c>col11</c>
</x>

HTML output:
------------------------------------------------------------------------
--------
|      |      |        grp1        |            grp2           |       |
|
|      |      |--------------------|---------------------------|       |
|
|      |      |      |      |      |      |     grp3    |      |       |
|
|      |      |      |      |      |      |-------------|      |       |
|
| col1 | col2 | col3 | col4 | col5 | col6 | col7 | col8 | col9 | col10 |
col11 |
------------------------------------------------------------------------
--------

CSV output:
    ,    ,    ,    ,    ,grp2,    ,    ,    ,     ,
    ,    ,grp1,    ,    ,    ,grp3,    ,    ,     ,
col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11


For HTML (this part is done already), I have a key that gets the <c> or
<g> elements at a specified depth - since col1, col2, col10, and col11
actually exist in the first <tr> of the table, they belong with grp1 and
grp2 at the top level. But those cells are bottom-valigned because
there's a data table beneath it, and it makes sense to have the label
sitting directly above it. In the CSV output, I need to alter the
structure so they actually appear there in the result document.

With that, here's the key I'm using for the HTML version:
    <key name="cols-at-depth" match="c|g[.//c]" use="count(ancestor::g)
+ 1"/>

Later in the stylesheet, I find the max column depth
($total-header-levels), start processing with key('cols-at-depth', 1)
and loop until I'm at key('cols-at-depth', $total-header-levels). But
for the CSV version, I essentially need to go the opposite way - rather
than counting the node's depth from its farthest <g> ancestor, I need to
count the depth of its deepest child branch. If I could do this with a
key, it would definitely be best, but just finding the algorithm to get
it in the first place would be a good start. My strategy from there is
to do a loop similar to the HTML cols-at-depth algorithm above, but the
CSV version would hold off on making the parent group entries until
absolutely necessary (at the point where the output is on the
nth-to-last output row, and parent group has at least one branch n
levels deep). Any ideas on XPath trickery I could use here?

I've included a trimmed-down version of the HTML-output stylesheet at
the bottom.


... and I know we've had this discussion before - I'm stuck with XSLT
1.0. Thanks in advance!

~ Scott



<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="html" encoding="utf-8"/>

    <xsl:key name="columns-at-depth" match="c|g[.//c]"
use="count(ancestor::g) + 1"/>

    <xsl:variable name="total-header-levels">
        <xsl:for-each select="//c">
            <xsl:sort select="count(ancestor::g)" data-type="number"/>
            <xsl:if test="position() = last()">
                <xsl:value-of select="count(ancestor::g) + 1"/>
            </xsl:if>
        </xsl:for-each>
    </xsl:variable>


    <xsl:template match="/">
        <table>
            <xsl:call-template name="loop-rows"/>
        </table>
    </xsl:template>

    <xsl:template name="loop-rows">
        <xsl:param name="row" select="1"/>
        <tr>
            <xsl:apply-templates select="key('columns-at-depth',
$row)"/>
        </tr>
        <xsl:if test="$row &lt; $total-header-levels">
            <xsl:call-templates name="loop-rows">
                <xsl:with-param name="row" select="$row + 1"/>
            </xsl:apply-templates>
        </xsl:if>
    </xsl:template>


    <xsl:template match="c">
        <th rowspan="{$total-header-levels - count(ancestor::g)}">
            <xsl:value-of select="."/>
        </th>
    </xsl:template>

    <xsl:template match="g">
        <th colspan="{count(.//c)}">
            <xsl:value-of select="@n"/>
        </th>
    </xsl:template>


</xsl:stylesheet>

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.