This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: Formatting elements. (flat -> group. For Jeni ).
- To: xsl-list at mulberrytech dot com
- Subject: Re: Formatting elements. (flat -> group. For Jeni ).
- From: Paul Tchistopolskii <paul at qub dot com>
- Date: Fri, 13 Oct 2000 22:32:37 -0700
- Organization: The Qub Group
- Reply-To: xsl-list at mulberrytech dot com
----- 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() > 1 ]", count={1} )
}
X:element "{$listname}" {
X:for-each "$list[ not(position() > $brkon) ]" {
X:element "{$elmname}" { !{.} }
}
}
!render-flat( list="$list[ position() > $brkon ]" )
} else {
X:element "{$elmname}" { !{ $list[1] } }
!render-flat( list="$list[ position() > 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) < number($hnum)" {
!get-brkon( cur= "$head" , list= "$list[ position() > 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() > 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() > $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() > $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() > 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) < number($hnum)">
<xsl:call-template name="get-brkon">
<xsl:with-param select="$head" name="cur"/>
<xsl:with-param select="$list[ position() > 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