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



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

> <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='bullet4'><text/></item>
> <item name='bullet5'><text/></item>
> <item name='bullet6'><text/></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>
> </document>
>
> which you want to be:
>
> <document>
> <title>Title field</title>
> <bulletlist>
>    <bullet>some text for item 1</bullet>
>    <bullet>some text for item 2</bullet>
>    <bullet></bullet>
>    <bullet></bullet>
>    <bullet></bullet>
>    <bullet></bullet>
> </bulletlist>
> <para>paragraph text</para>
> <bulletlist>
>    <bullet>some text for item 1</bullet>
>    <bullet>some text for item 2</bullet>
>    <bullet></bullet>
>    <bullet></bullet>
> </bulletlist>
> </document>
>

Below please find another  ( pure functional ) solution.

I'll first give XSLScript notation and then will be the XSL code
( generated, as usual ). I think this should illustrate the
real value of terseness.

I think the biggest problem of this transformation is XSL verbosity,
because the transformation itself is not complex at all.
It is Composed of  2 simple steps :

If it is 'bullet' - see when 'bulletlist'   ends : split on that point and
call yourself again.

I think this 'split / call yourself '  is the the core pattern which
any XSL developer should learn ( the same happens with
counters e t.c. )

There is a small 'drawback' similar to 'drawback' of my solution to
Sebastian's test6, but I'm better not to start this all again.

Whatever.


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:if "starts-with( $type, 'bullet' )"  {
                      <% X:var fnbul={ <% !first-non-bul( list="$list", count={1} ) %> }
%>

                      <bulletlist>
                           <% X:for-each "$list[ position() &lt; $fnbul ]" {
                                <bullet> <% {.} %> </bullet>
                           } %>
                      </bulletlist>

                      <% !render-flat( list="$list[ not ( position() &lt; $fnbul )]" ) %>
          } else

                  <% X:element "{$type}" {
                       <% { $list[1] } %>
                  } %>

                  <% !render-flat( list="$list[ position() &gt; 1]" ) %>
         } %>
  } %>
}

X:template first-non-bul( list, count ) {

     <% X:if "$list" {
            <% X:var type="string($list[1]/@name)" %>

            <% X:if "starts-with( $type, 'bullet' )"  {
                    <% !first-non-bul( list="$list[ position() &gt; 1 ]", count="$count +
1" ) %>
            } else {
                   <% {$count} %>
            } %>
     } else {
          <% {$count} %>
     } %>
}

}

Here is the XSL.
------------------------

<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:choose>
            <xsl:when test="starts-with( $type, 'bullet' )">
               <xsl:variable name="fnbul">
                  <xsl:call-template name="first-non-bul">
                     <xsl:with-param select="$list" name="list"/>
                     <xsl:with-param name="count">1</xsl:with-param>
                  </xsl:call-template>
               </xsl:variable>
               <bulletlist>
                  <xsl:for-each select="$list[ position() &lt; $fnbul ]">
                     <bullet>
                        <xsl:value-of select="."/>
                     </bullet>
                  </xsl:for-each>
               </bulletlist>
               <xsl:call-template name="render-flat">
                  <xsl:with-param select="$list[ not ( position() &lt; $fnbul )]"
name="list"/>
               </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
               <xsl:element name="{$type}">
                  <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="first-non-bul">
      <xsl:param name="list"/>
      <xsl:param name="count"/>
      <xsl:choose>
         <xsl:when test="$list">
            <xsl:variable select="string($list[1]/@name)" name="type"/>
            <xsl:choose>
               <xsl:when test="starts-with( $type, 'bullet' )">
                  <xsl:call-template name="first-non-bul">
                     <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: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]