This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Formatting elements. (flat -> group. For Jeni ).



----- Original Message -----
From: Jeni Tennison <mail@jenitennison.com>

> I'm be very grateful if
> you could post the (generated) XSLT from the completed solution (with the
> new first-breaking-pos template) so that I can see more clearly how to
> apply it in future cases where I'm faced with this problem.

Sorry - it took some time for me to rewrite the XSLScript parser itself
( I wanted to use a new XSLScript syntax for this example.)

As promised - the stylesheet structure remains the same - just
a bunch of new functions added ( XSLT is now huge ;-).

I'm not happy with the results ( even it took 15 minutes to write
this beast and it could be shorter - some functions are for
readability only, but... )

In the next version of XSLScript I'll try approaching some more non-XSLT
macro-constructions  ( similar to 'else' , but related to recursion ). Anybody
wants to help in brainstorming?  I know about the Oliver's loop solution, but
I'm thinking about something more flexible. Maybe saxon:evaluate is our
friend? Ah, nevermind...

Input:

<document>
 <item name='title'><text>Title field</text></item>
 <item name='bullet1'><text>some text for item 1</text></item>
 <item name='bullet2'><text>some text for item 2</text></item>
 <item name='bullet3'><text/></item>
 <item name='bullet1'><text/></item>
 <item name='bullet2'><text/></item>
 <item name='bullet3'>some text for item 3</item>
 <item name='para'><text>paragraph text</text></item>
 <item name='bullet1'><text>some text for item 1</text></item>
 <item name='bullet2'><text>some text for item 2</text></item>
 <item name='bullet3'><text/></item>
 <item name='bullet4'><text/></item>
 <item name='para'><text>paragraph text</text></item>
 <item name='menu1'><text>some text for menu 1</text></item>
 <item name='menu2'><text>some text for menu 2</text></item>
 <item name='menu3'><text/></item>
 <item name='menu1'><text>some text for menu 1</text></item>
 <item name='menu2'><text>some text for menu 2</text></item>
 <item name='menu3'><text/></item>
</document>

Output:

C:\WORK\XslScript\XslScript07>xsls flat.xml flat.xsls
<?xml version="1.0" encoding="utf-8"?>
<document>
   <title>Title field</title>
   <bulletlist>
      <bullet>some text for item 1</bullet>
      <bullet>some text for item 2</bullet>
      <bullet/>
   </bulletlist>
   <bulletlist>
      <bullet/>
      <bullet/>
      <bullet>some text for item 3</bullet>
   </bulletlist>
   <para>paragraph text</para>
   <bulletlist>
      <bullet>some text for item 1</bullet>
      <bullet>some text for item 2</bullet>
      <bullet/>
      <bullet/>
   </bulletlist>
   <para>paragraph text</para>
   <menulist>
      <menu>some text for menu 1</menu>
      <menu>some text for menu 2</menu>
      <menu/>
   </menulist>
   <menulist>
      <menu>some text for menu 1</menu>
      <menu>some text for menu 2</menu>
      <menu/>
   </menulist>
</document>

XSLScript code:

X:transform {

X:output indent="yes";

X:template = "document" {
 <document> !render-flat( list="item" ) </document>
}

X:template render-flat( list ) {

     X:if "$list" {
         X:var type = "string($list[1]/@name)"
         X:var listname = { !get-listname( itm="$type" ) }
         X:var elmname  = { !get-elmname( itm="$type" ) }

        X:if "string($listname)"  {

              X:var
on={ 
                   !get-brkon( cur="$type", list="$list[ position() &gt; 1 ]", count={1} ) 
              }
                
              X:element "{$listname}" {
                 X:for-each "$list[ not(position() &gt; $brkon) ]" {
                       X:element "{$elmname}" { !{.} }
                 }
              }

              !render-flat( list="$list[ position() &gt; $brkon ]" )

     } else {

              X:element "{$elmname}" { !{ $list[1] } }
              !render-flat( list="$list[ position() &gt; 1]" ) 
     }
  }
}

X:template get-listname( itm ) {
     X:choose {
          X:when "starts-with( $itm, 'bull
et' )" {bulletlist}
          X:when "starts-with( $itm, 'menu' )" {menulist}
          X:otherwise {}
     }
}

X:template get-elmname( itm ) {
     X:choose {
          X:when "starts-with( $itm, 'bullet' )" {bullet}
          X:when "starts-with( $itm, 'menu' )" {menu}
          X:otherwise { !{$itm} }
     }
}

X:template get-brkon( cur, list, count ) {

  X:if "$list" {

  X:var curel = { !get-elmname( itm="$cur" ) }
  X:var curnum = { !get-number( itm="$cur" ) }

  X:var head = "string($list[1]/@name)"

  X:var hel = { !get-elmname( itm="$head" ) }
  X:var hnum = { !get-number( itm="$head" ) }

          X:if " $curel = $hel and number($curnum) &lt; number($hnum)" {
                   !get-brkon( cur= "$head" , list= "$list[ position() &gt; 1 ]" , count=
"$count + 1" )
          } else {
                  !{$count}
          }
 } else {
         !{$count}
 }
}

X:template get-number( itm )

     !{translate($itm, 'abcdefghijklmnopqrstuvwxyz', ' ')}
}

}

XSLT ( generated ):

<?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="document">
      <document>
         <xsl:call-template name="render-flat">
            <xsl:with-param select="item" name="list"/>
         </xsl:call-template>
      </document>
   </xsl:template>

   <xsl:template name="render-flat">
      <xsl:param name="list"/>
      <xsl:if test="$list">
         <xsl:variable select="string($list[1]/@name)" name="type"/>
         <xsl:variable name="listname">
            <xsl:call-template name="get-listname">
               <xsl:with-param select="$type" name="itm"/>
            </xsl:call-template>
         </xsl:variable>
         <xsl:variable name="elmname">
            <xsl:call-template name="get-elmname">
               <xsl:with-param select="$type" name="itm"/>
            </xsl:call-template>
         </xsl:variable>
         <xsl:choose>
            <xsl:when test="string($listname)">
               <xsl:variable name="brkon">
                  <xsl:call-template name="get-brkon">
                     <xsl:with-param select="$type" name="cur"/>
                     <xsl:with-param select="$list[ position() &gt; 1 ]" name="list"/>
                     <xsl:with-param name="count">1</xsl:with-param>
                  </xsl:call-template>
               </xsl:variable>
               <xsl:element name="{$listname}">
                  <xsl:for-each select="$list[ not(position() &gt; $brkon) ]">
                     <xsl:element name="{$elmname}">
                        <xsl:value-of select="."/>
                     </xsl:element>
                  </xsl:for-each>
               </xsl:element>
               <xsl:call-template name="render-flat">
                  <xsl:with-param select="$list[ position() &gt; $brkon ]" name="list"/>
               </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
               <xsl:element name="{$elmname}">
                  <xsl:value-of select=" $list[1]"/>
               </xsl:element>
               <xsl:call-template name="render-flat">
                  <xsl:with-param select="$list[ position() &gt; 1]" name="list"/>
               </xsl:call-template>
            </xsl:otherwise>
         </xsl:choose>
      </xsl:if>
   </xsl:template>

   <xsl:template name="get-listname">
      <xsl:param name="itm"/>
      <xsl:choose>
         <xsl:when test="starts-with( $itm, 'bullet' )">bulletlist</xsl:when>
         <xsl:when test="starts-with( $itm, 'menu' )">menulist</xsl:when>
         <xsl:otherwise/>
      </xsl:choose>
   </xsl:template>

   <xsl:template name="get-elmname">
      <xsl:param name="itm"/>
      <xsl:choose>
         <xsl:when test="starts-with( $itm, 'bullet' )">bullet</xsl:when>
         <xsl:when test="starts-with( $itm, 'menu' )">menu</xsl:when>
         <xsl:otherwise>
            <xsl:value-of select="$itm"/>
         </xsl:otherwise>
      </xsl:choose>
   </xsl:template>

   <xsl:template name="get-brkon">
      <xsl:param name="cur"/>
      <xsl:param name="list"/>
      <xsl:param name="count"/>
      <xsl:choose>
         <xsl:when test="$list">
            <xsl:variable name="curel">
               <xsl:call-template name="get-elmname">
                  <xsl:with-param select="$cur" name="itm"/>
               </xsl:call-template>
            </xsl:variable>
            <xsl:variable name="curnum">
               <xsl:call-template name="get-number">
                  <xsl:with-param select="$cur" name="itm"/>
               </xsl:call-template>
            </xsl:variable>
            <xsl:variable select="string($list[1]/@name)" name="head"/>
            <xsl:variable name="hel">
               <xsl:call-template name="get-elmname">
                  <xsl:with-param select="$head" name="itm"/>
               </xsl:call-template>
            </xsl:variable>
            <xsl:variable name="hnum">
               <xsl:call-template name="get-number">
                  <xsl:with-param select="$head" name="itm"/>
               </xsl:call-template>
            </xsl:variable>
            <xsl:choose>
               <xsl:when test=" $curel = $hel and number($curnum) &lt; number($hnum)">
                  <xsl:call-template name="get-brkon">
                     <xsl:with-param select="$head" name="cur"/>
                     <xsl:with-param select="$list[ position() &gt; 1 ]" name="list"/>
                     <xsl:with-param select="$count + 1" name="count"/>
                  </xsl:call-template>
               </xsl:when>
               <xsl:otherwise>
                  <xsl:value-of select="$count"/>
               </xsl:otherwise>
            </xsl:choose>
         </xsl:when>
         <xsl:otherwise>
            <xsl:value-of select="$count"/>
         </xsl:otherwise>
      </xsl:choose>
   </xsl:template>

   <xsl:template name="get-number">
      <xsl:param name="itm"/>
      <xsl:value-of select="translate($itm, 'abcdefghijklmnopqrstuvwxyz', ' ')"/>
   </xsl:template>
</xsl:stylesheet>




 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]