Re: [xsl] empty elements to filled without overlapping hierachies

Subject: Re: [xsl] empty elements to filled without overlapping hierachies
From: James Cummings <James.Cummings@xxxxxxxxxxxxxx>
Date: Thu, 13 Nov 2003 14:01:59 +0000 (GMT)
On Thu, 13 Nov 2003, Jeni Tennison wrote:

> That's absolutely correct. Stripping the whitespace-only text nodes
> with <xsl:strip-space> is the easiest way to get around the problem, I
> thought. Otherwise things get pretty fiddly.

Seems to work fine.

> Yes. Rather than using <xsl:copy-of> inside the newly-created <Q>
> elements, apply templates to the nodes that will make up the content
> of the <Q> elements. You want to copy the <SSD> elements:

Changed them to apply-templates.

> <xsl:template match="text()">
>   <xsl:for-each select="tokenize(., '\n')">
>     <l><xsl:value-of select="normalize-space(.)" /></l>
>   </xsl:for-each>
> </xsl:template>

And this tokenizes the text() until it reaches a newline or
a child element (like SSD).  Does this mean that if a SSD was
in the middle of a line (they aren't) for some reason you'd
get <l>blah blah</l><SSD value="foo"/><l>blah blah</>  ?

> You could use <xsl:analyze-string> rather than the tokenize() function
> if you prefer.
would that have the same effect?  (another XSLT2 thing I've not
played with yet.)

To summarise, this is what I've don't with the xsl:
--------
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; >
<xsl:output indent="yes" />
<xsl:strip-space elements="body"/>

<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>

<xsl:template match="body">
  <body>
  <xsl:apply-templates select="TITLE|FRONT"/>
    <xsl:for-each-group select="node() except (TITLE|FRONT)"
                        group-starting-with="SN">
      <SN value="{@value}">
        <xsl:for-each-group select="current-group()[position() > 1]"
                            group-starting-with="Q">
          <xsl:choose>
            <xsl:when test="not(self::Q)">
              <xsl:apply-templates select="current-group()" />
            </xsl:when>
            <xsl:when test="current-group()[last()][self::SSD]">
              <Q value="{@value}">
                <xsl:apply-templates select="(current-group() except .)
                                       [position() != last()]" />
              </Q>
              <xsl:apply-templates select="current-group()[last()]" />
            </xsl:when>
            <xsl:otherwise>
              <Q value="{@value}">
               <xsl:apply-templates select="current-group() except ." />
              </Q>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:for-each-group>
      </SN>
    </xsl:for-each-group>
  </body>
</xsl:template>

<xsl:template match="SSD|FRONT|TITLE">
  <xsl:copy-of select="." />
 </xsl:template>

<xsl:template match="text()">
<xsl:if test=". !=''">
  <xsl:for-each select="tokenize(., '\n')">
    <l><xsl:value-of select="normalize-space(.)" /></l>
  </xsl:for-each>
  </xsl:if>
</xsl:template>
</xsl:stylesheet>
------

Since it seems to work I'll assume I've done the change
from copy-of to apply-templates ok.  I suppose what I'd be
tempted to do next is make it more general so that it can
be applied to similarly structured files with slightly different
names.  Perhaps use variables/params to allow these to be easily
changed?

Thanks again for your generous help,
James

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

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


Current Thread