xsl-list
[Top] [All Lists]

Re: empty elements to filled without overlapping hierachies

2003-11-13 07:01:59
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="{(_at_)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="{(_at_)value}">
                <xsl:apply-templates select="(current-group() except .)
                                       [position() != last()]" />
              </Q>
              <xsl:apply-templates select="current-group()[last()]" />
            </xsl:when>
            <xsl:otherwise>
              <Q value="{(_at_)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(_dot_)Cummings(_at_)ota(_dot_)ahds(_dot_)ac(_dot_)uk

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