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="{(_at_)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="{(_at_)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="{(_at_)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="{(_at_)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(_dot_)Cummings(_at_)ota(_dot_)ahds(_dot_)ac(_dot_)uk
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list