[xsl] merging readings with children

Subject: [xsl] merging readings with children
From: James Cummings <James.Cummings@xxxxxxxxx>
Date: Wed, 28 May 2003 13:49:18 +0100 (BST)
Hi all,

A little while back I asked a question about merging alternate readings
in a critical edition, and got some very helpful replies.  Most notably
from David Carlisle.  The original question proposed a text like:
------original.xml------
<?xml version="1.0"?>
<foo>
<p id="a1"><body wit="A B C D E">This is a
     <app><rdg wit="A C D">test</rdg>
        <rdg wit="B E">testament</rdg></app>,
     really. </body>
</p>
 <p id="a2">
 <body wit="A B C D E">This is a
<app>
      <rdg wit="A D">test</rdg>
      <rdg wit="B C E">testament</rdg></app>
a really
<app>
    <rdg wit="A E">long</rdg>
    <rdg wit="B C">important</rdg>
    <rdg wit="D">boring</rdg>
</app>test!
</body>
<body wit="F">This is a different body element</body>
  </p>
</foo>
------
And David Carlisle and others suggested the readings
could be merged using saxon:node-set as follows:
------original.xsl------
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="1.0"
xmlns:saxon="http://icl.com/saxon"; extension-element-prefixes="saxon" >
<xsl:output indent="yes"/>
<xsl:variable name="wits">
<x>A</x><x>B</x><x>C</x><x>D</x><x>E</x><x>F</x>
</xsl:variable>

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

<xsl:key name="k" match="body" use="."/>

<xsl:template match="p"><p id="{@id}">
<xsl:variable name="p" select="."/>
<xsl:variable name="one">
 <xsl:for-each select="saxon:node-set($wits)/*">
 <body wit="{.}">
  <xsl:variable name="x">
   <xsl:apply-templates mode="wit" select="$p/node()">
   <xsl:with-param name="wit" select="."/>
   </xsl:apply-templates>
  </xsl:variable>
 <xsl:value-of select="normalize-space($x)"/>
 </body>
 </xsl:for-each>
</xsl:variable>

<xsl:for-each select="saxon:node-set($one)/*">
<xsl:if test="generate-id(.)=generate-id(key('k',.))">
<body><xsl:attribute name="wit">
   <xsl:for-each select="key('k',.)">
   <xsl:value-of select="@wit"/>
   <xsl:if test="position()&lt;last()"><xsl:text> </xsl:text></xsl:if>
   </xsl:for-each>
   </xsl:attribute><xsl:value-of select="."/></body>
   </xsl:if>
</xsl:for-each>
</p>
</xsl:template>

<xsl:template mode="wit" match="*">
 <xsl:param name="wit"/>
 <xsl:if test="not(@wit) or (@wit and contains(@wit,$wit))">
  <xsl:apply-templates mode="wit">
    <xsl:with-param name="wit" select="$wit"/>
  </xsl:apply-templates>
 </xsl:if>
 </xsl:template>
</xsl:stylesheet>
------
This, as expected, produces output such as:
------output.xml------
<?xml version="1.0" encoding="utf-8"?>
<foo>
   <p id="a1">
      <body wit="A C D">This is a test, really.</body>
      <body wit="B E">This is a testament, really.</body>
      <body wit="F"/>
   </p>
   <p id="a2">
      <body wit="A">This is a test a really long test!</body>
      <body wit="B C">This is a testament a really important test!</body>
      <body wit="D">This is a test a really boring test!</body>
      <body wit="E">This is a testament a really long test!</body>
      <body wit="F">This is a different body element</body>
   </p>
</foo>
------

Now the question (finally!) is whether there any possible way of merging
readings that contain child elements?  Let's say the original.xml
contained a <note>notecontents</note> element that needed
to be changed to something along the lines of:
 <span class="note">note-contents</span>
inside the readings:
------
 <body wit="A B C D E">This is a
<app>
      <rdg wit="A D">test</rdg>
      <rdg wit="B E">testament</rdg>
      <rdg wit="C"><note>test</note>testament</rdg></app>
a really
<app>
    <rdg wit="A E"><note>test2</note>long</rdg>
    <rdg wit="B C">important</rdg>
    <rdg wit="D">boring</rdg>
</app>test!
</body>
------

Simply adding:
<xsl:template match="note">
<span class="note"><xsl:apply-templates /></span>
</xsl:template>

does not work.  If the template match is specified as mode="wit",
then in is picked up while the wits are being processed, but the
<span> element isn't created.  I'm assuming this is because of
the programatic way the p template match uses value-of, but
all my attempts to do this another way have so far failed.  I'm
attempting to keep this as generalistic as possible in the
matching of child elements like <note> because they themselves
might have their own child elements that I'd also like to be able
to match.  I don't mind doing multiple stylesheets, but can't
conceive how the above would work, since the descendents
obviously need to be included in the comparison.

Any suggestions or help would be gratefully received, on or off-list.

-James
-- 
Dr James Cummings, James.Cummings@xxxxxxxxx, http://www.uea.ac.uk/~q503
Cursus Project, School of Music, University of East Anglia,
Norwich, Norfolk, NR4 7TJ, UK  Tel:(01603)593-595



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


Current Thread