xsl-list
[Top] [All Lists]

Re: [xsl] Maximum "child-depth" of current node?

2007-10-16 10:23:47
As far as the issue at hand, this might've gotten lost:

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


The provided link to Dave Pawson's FAQ contains XSLT 1.0 solutions.

Also, certainly, one could use FXSL 1.x instead of FXSL 2.0.

Thanks for your reply. I'm a big fan of your FXSL methods - I'd actually
like to speak with you sometime about some extension ideas I had a while
ago. Please e-mail me at your convenience if you'd be interested in
hearing them.

Thank you Scott. Feel free to email me.


-- 
Cheers,
Dimitre Novatchev
---------------------------------------
Truly great madness cannot be achieved without significant intelligence.
---------------------------------------
To invent, you need a good imagination and a pile of junk
-------------------------------------
You've achieved success in your field when you don't know whether what
you're doing is work or play





On 10/16/07, Scott Trenda <Scott(_dot_)Trenda(_at_)oati(_dot_)net> wrote:
Dmitre,

Thanks for your reply. I'm a big fan of your FXSL methods - I'd actually
like to speak with you sometime about some extension ideas I had a while
ago. Please e-mail me at your convenience if you'd be interested in
hearing them.

As far as the issue at hand, this might've gotten lost:

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


~ Scott


-----Original Message-----
From: Dimitre Novatchev [mailto:dnovatchev(_at_)gmail(_dot_)com]
Sent: Tuesday, October 16, 2007 12:03 PM
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: Re: [xsl] Maximum "child-depth" of current node?

Do have a look here:

http://www.dpawson.co.uk/xsl/sect2/N2193.html


The most up-to-date XSLT 2.0 code  is:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
 xmlns:xs="http://www.w3.org/2001/XMLSchema";
 xmlns:f="http://fxsl.sf.net/";
 exclude-result-prefixes="xs f"


 <xsl:import href="../f/func-map.xsl"/>

 <xsl:function name="f:maxDepth" as="xs:integer">
  <xsl:param name="pNode" as="node()"/>

  <xsl:sequence select=
   "if(not($pNode/node())) then 0
      else
        max(f:map(f:maxDepth(), $pNode/node() ) ) + 1
   "
   />
 </xsl:function>

 <xsl:function name="f:maxDepth" as="element()">
   <f:maxDepth/>
 </xsl:function>

 <xsl:template match="f:maxDepth" mode="f:FXSL" as="xs:integer">
   <xsl:param name="arg1" as="node()"/>

   <xsl:sequence select="f:maxDepth($arg1)"/>
 </xsl:template>
 </xsl:stylesheet>

and the logic is concentrated just in these three lines:

    if(not($pNode/node())) then 0
      else
        max(f:map(f:maxDepth(), $pNode/node() ) ) + 1




--
Cheers,
Dimitre Novatchev
---------------------------------------
Truly great madness cannot be achieved without significant intelligence.
---------------------------------------
To invent, you need a good imagination and a pile of junk
-------------------------------------
You've achieved success in your field when you don't know whether what
you're doing is work or play




On 10/16/07, Scott Trenda <Scott(_dot_)Trenda(_at_)oati(_dot_)net> wrote:
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>

--~------------------------------------------------------------------
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>
--~--



--~------------------------------------------------------------------
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>
--~--


--~------------------------------------------------------------------
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>
--~--



--~------------------------------------------------------------------
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>
--~--

<Prev in Thread] Current Thread [Next in Thread>