[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: empty elements to filled without overlapping hiera

Subject: Re: empty elements to filled without overlapping hierachies
From: James Cummings <James.Cummings@xxxxxxxxxxxxxx>
Date: Thu, 13 Nov 2003 11:23:49 +0000 (GMT)
sn element
On Wed, 12 Nov 2003, Jeni Tennison wrote:

> Let's try to find an XSLT 2.0 solution. It will use
> <xsl:for-each-group> with the group-starting-with option, which groups
> together items such that each group starts with the same thing.

This works, though I'm confused about one tiny bit, I'll mention further down, but
let me make sure I understand how it is working first.  (I do
*try* and learn rather than just leech your generous help...I'm just
not always that good at it ;-) )

> The first level of grouping is <SN>s. We want to group all the
> child nodes of the <body> element, aside from the <TITLE> element,
> into groups that start with a particular <SN> element. For each of
> these groups, we want to create a <SN> element with the value
> attribute from the original <SN>:
>
> <xsl:template match="body">
>   <body>
>     <xsl:copy-of select="TITLE" />
>     <xsl:for-each-group select="node() except TITLE"
>                         group-starting-with="SN">
>       <SN value="{@value}">
>         ...
>       </SN>
>     </xsl:for-each-group>
>   </body>
> </xsl:template>

So this takes any node() which includes the child elements and
any text() nodes and groups them together (except for TITLE)
as starting with SN.  I've never used @group-starting-with
before that does seem very handy.

> Next, we want to take the elements in that group (aside from the <SN>
> element itself) and group them into groups starting with <Q> elements.
> Now, there are three possible arrangements of these groups:
>
>   1. The very first group might not start with a <Q> element; in that
>      case, we just want to copy all the items in that group.
>
>   2. The group might end with a <SSD> element, in which case we want
>      to have a <Q> element that contains all the items in the group
>      aside from that final <SSD> element (and the <Q> element itself).
>
>   3. The group might end with something other than a <SSD> element, in
>      which case we want to have a <Q> element that contains all the
>      items in the group aside from the <Q> element itself
>
> <xsl:template match="body">
>   <body>
>     <xsl:copy-of select="TITLE" />
>     <xsl:for-each-group select="node() except TITLE"
>                         group-starting-with="SN">
>       <SN value="{@value}">
>         <xsl:for-each-group select="current-group() except ."
>                             group-starting-with="Q">

except .in this context being whatever is in group-starting-with above?

>           <xsl:choose>
>             <xsl:when test="not(self::Q)">
>               <xsl:copy-of select="." />
>             </xsl:when>

So case 1 above, copy anything that isn't Q

>             <xsl:when test="current-group()[last()][self::SSD]">
>               <Q value="{@value}">
>                 <xsl:copy-of select="(current-group() except .)
>                                        [position() != last()]" />
>               </Q>
>               <xsl:copy-of select="current-group()[last()]" />
>             </xsl:when>

So case 2 above, close the Q before the last SSD - this is where
my real question is.  If I don't include <xsl:strip-space
elements="body" /> This doesn't work right so you get:
 <Q value="foo">blah blah blah
 <SSD value="blah"/></Q>
instead of
 <Q value="foo">blah blah blah
 </Q><SSD value="blah"/>
but I'm not confident about what that is.  Is it because the
original might have had something like:
 <Q value="foo"/>blah blah blah
 <SSD value="blah"/>
 [whitespacenode]

Or am I misunderstanding that?

>             <xsl:otherwise>
>               <Q value="{@value}">
>                 <xsl:copy-of select="current-group() except ." />
>               </Q>
>             </xsl:otherwise>
>           </xsl:choose>
>         </xsl:for-each-group>
>       </SN>
>     </xsl:for-each-group>
>   </body>
> </xsl:template>

Is there simultaneously an easy way to add in additional markup for the
individual lines inside of Q? i.e. either: <l>blah</l> or blah<lb/>?
so:
 <Q value="foo"><l>blah blah blah</l>
 <l>blah blah blah blah blah</l>
 <l>blah blah blah blah blah</l><SSD value="foo"/>
 <l>blah blah blah blah blah</l></Q>
 <SSD value="blort"/>


> An XSLT 1.0 solution would be harder...

Yes, certainly.  I'm assuming it isn't necessarily impossible?  But
XSLT2 is fine with me ;-)

Offlist someone suggested the route of doing COCOA/OCP -> SGML with
omitted end-tags, create DTD specifying the relationships of
SN/Q/SSD, then sgml2xml conversion.  This leads to any SSD at
the very end of a Q being included inside the Q since SSD has
to be allowed inside Q at some points.

Many Thanks,

-James


---
Dr James Cummings, Oxford Text Archive, James.Cummings@xxxxxxxxxxxxxx

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


Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.