xsl-list
[Top] [All Lists]

Re: [xsl] Identifier attribute (was: Re: [xsl] Creating Hierarchy)

2008-10-23 11:08:26
At 2008-10-23 15:15 +0100, Rowan Sylvester-Bradley wrote:
Thanks for your help with this. Using the technique you've suggested I've been able to successfully add the id values with two separate XSL transform documents, but I can't get it to work as a two-pass process in a single stylesheet.
...
How do I combine these two transforms into a single stylesheet using the two-pass approach? I can't get this to work...

Below is an example, and I've copied your original components for the archive.

Fortunately, since you don't have any template matches in your first pass (other than the root), you don't need to muck with modes for the second pass. If, however, you do have matches in both passes, then choose one of the passes to use the default unnamed mode and use explicit modes for the other pass(es). Note how for the second pass I'm explicitly avoiding the root node in order to prevent an infinite loop.

I hope this helps.

. . . . . . . . . . . . Ken

T:\ftemp>type rowan.xml
<?xml version="1.0"?>
<mytree>
<node>
  <name>Root of my tree</name>
  <level>0</level>
</node>
<node>
  <name>Child of root</name>
  <level>1</level>
</node>
<node>
  <name>Another child of root</name>
  <level>1</level>
</node>
<node>
  <name>Grandchild of root</name>
  <level>2</level>
</node>
<node>
  <name>Yet another child of root</name>
  <level>1</level>
</node>
</mytree>



T:\ftemp>type rowan1.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="2.0">
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="/">
        <xsl:call-template name="next-level">
              <xsl:with-param name="level" select="0"/>
              <xsl:with-param name="nodes" select="//node"/>
        </xsl:call-template>
  </xsl:template>
  <xsl:template name="next-level">
     <xsl:param name="level"/>
     <xsl:param name="nodes"/>
     <xsl:if test="$nodes/level[.=$level]">
        <!-- then group the nodes at this level -->
<xsl:for-each-group select="$nodes" group-starting-with="node[level[.=$level]]"> <!-- act on the first of each group only, passing others to next level -->
           <newnode id="">
              <xsl:copy-of select="name"/>
<!-- group at the next level assuming monotonically increasing level -->
              <xsl:call-template name="next-level">
                 <xsl:with-param name="level" select="$level + 1"/>
<xsl:with-param name="nodes" select="current-group()[position()&gt;1]"/>
              </xsl:call-template>
           </newnode>
        </xsl:for-each-group>
     </xsl:if>
  </xsl:template>
</xsl:stylesheet>


T:\ftemp>call xslt2 rowan.xml rowan1.xsl rowan1.xml

T:\ftemp>type rowan1.xml
<?xml version="1.0" encoding="UTF-8"?>
<newnode id="">
   <name>Root of my tree</name>
   <newnode id="">
      <name>Child of root</name>
   </newnode>
   <newnode id="">
      <name>Another child of root</name>
      <newnode id="">
         <name>Grandchild of root</name>
      </newnode>
   </newnode>
   <newnode id="">
      <name>Yet another child of root</name>
   </newnode>
</newnode>
T:\ftemp>type rowan2.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="2.0"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema";>
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="*[(_at_)id]">
    <xsl:copy>
      <xsl:attribute name="id">
        <xsl:number level="any" count="*[(_at_)id]"/>
      </xsl:attribute>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

T:\ftemp>call xslt2 rowan1.xml rowan2.xsl rowan2.xml

T:\ftemp>type rowan2.xml
<?xml version="1.0" encoding="UTF-8"?>
<newnode id="1">
   <name>Root of my tree</name>
   <newnode id="2">
      <name>Child of root</name>
   </newnode>
   <newnode id="3">
      <name>Another child of root</name>
      <newnode id="4">
         <name>Grandchild of root</name>
      </newnode>
   </newnode>
   <newnode id="5">
      <name>Yet another child of root</name>
   </newnode>
</newnode>
T:\ftemp>type rowan.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="2.0">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <xsl:variable name="pass1">
      <xsl:call-template name="next-level">
        <xsl:with-param name="level" select="0"/>
        <xsl:with-param name="nodes" select="//node"/>
      </xsl:call-template>
    </xsl:variable>
    <xsl:apply-templates select="$pass1/node()"/>
  </xsl:template>

  <xsl:template name="next-level">
     <xsl:param name="level"/>
     <xsl:param name="nodes"/>
     <xsl:if test="$nodes/level[.=$level]">
        <!-- then group the nodes at this level -->
<xsl:for-each-group select="$nodes" group-starting-with="node[level[.=$level]]"> <!-- act on the first of each group only, passing others to next level -->
           <newnode id="">
              <xsl:copy-of select="name"/>
<!-- group at the next level assuming monotonically increasing level -->
              <xsl:call-template name="next-level">
                 <xsl:with-param name="level" select="$level + 1"/>
<xsl:with-param name="nodes" select="current-group()[position()&gt;1]"/>
              </xsl:call-template>
           </newnode>
        </xsl:for-each-group>
     </xsl:if>
  </xsl:template>

  <xsl:template match="*[(_at_)id]">
    <xsl:copy>
      <xsl:attribute name="id">
        <xsl:number level="any" count="*[(_at_)id]"/>
      </xsl:attribute>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

T:\ftemp>call xslt2 rowan.xml rowan.xsl rowan3.xml

T:\ftemp>type rowan3.xml
<?xml version="1.0" encoding="UTF-8"?>
<newnode id="1">
   <name>Root of my tree</name>
   <newnode id="2">
      <name>Child of root</name>
   </newnode>
   <newnode id="3">
      <name>Another child of root</name>
      <newnode id="4">
         <name>Grandchild of root</name>
      </newnode>
   </newnode>
   <newnode id="5">
      <name>Yet another child of root</name>
   </newnode>
</newnode>
T:\ftemp>rem Done!

T:\ftemp>rem



--
Upcoming XSLT/XSL-FO hands-on courses:      Wellington, NZ 2009-01
Training tools: Comprehensive interactive XSLT/XPath 1.0/2.0 video
Video sample lesson:    http://www.youtube.com/watch?v=PrNjJCh7Ppg
Video course overview:  http://www.youtube.com/watch?v=VTiodiij6gE
G. Ken Holman                 mailto:gkholman(_at_)CraneSoftwrights(_dot_)com
Crane Softwrights Ltd.          http://www.CraneSoftwrights.com/s/
Male Cancer Awareness Nov'07  http://www.CraneSoftwrights.com/s/bc
Legal business disclaimers:  http://www.CraneSoftwrights.com/legal


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