rejoin.xslt

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
		xmlns:html="http://www.w3.org/1999/xhtml"
		xmlns:xlink="http://www.w3.org/1999/xlink"
		version="1.0"
>
  <xsl:output doctype-system="cexml_message.dtd"
	      indent="yes"
	      />

  <xsl:template match="/">
    <xsl:apply-templates select="cexml"/>
  </xsl:template>
	
  <xsl:template match="cexml">
    <xsl:element name="cexml">
      <xsl:apply-templates select="builtobject" />
      <xsl:apply-templates select="quantification" />
      <xsl:apply-templates select="function" />
      <xsl:apply-templates select="unit" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="builtobject">
    <xsl:element name="builtobject">
      <xsl:call-template name="copy-attributes"/>
      <xsl:choose>
	<xsl:when test='self::node()[@mode="view"]'>
	  <xsl:param name="target">
	    <xsl:value-of select="string(./name)"/>
	  </xsl:param>
	  <!-- search in the tree for a builtobject with a builtobject
	  parent in order *not* to find some builtobject with a
	  characteristics parent... Then copy that builobject's names
	  -->
	  <xsl:apply-templates
	  select="//builtobject/builtobject[name=string($target)]" 
	  mode="snatch" />
	</xsl:when>
	<xsl:otherwise>
	  <xsl:apply-templates select="name" />
	</xsl:otherwise>
      </xsl:choose>
      <xsl:apply-templates select="characteristics" />
      <xsl:apply-templates select="builtobject" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="characteristics">
    <xsl:element name="characteristics">
      <xsl:call-template name="copy-attributes"/>
      <!-- all other elements below characteristics need rejoining,
      except "amount" --> 
      <xsl:if test='not(../@mode="search")'>
	<xsl:apply-templates select="builtobject" mode="rejoin"/>
	<xsl:apply-templates select="amount" />
	<xsl:apply-templates select="quantification" mode="rejoin" />
	<xsl:apply-templates select="function" mode="rejoin" />
      </xsl:if>
      <xsl:if test='../@mode="search"'>
	<xsl:apply-templates select="builtobject" />
	<xsl:apply-templates select="amount" />
	<xsl:apply-templates select="quantification" />
	<xsl:apply-templates select="function" />
      </xsl:if>
    </xsl:element>
  </xsl:template>

  <xsl:template match="name">
    <xsl:element name="name">
      <xsl:call-template name="copy-attributes"/>
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="amount">
    <xsl:element name="amount">
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="quantification">
    <xsl:element name="quantification">
      <xsl:call-template name="copy-attributes"/>
      <xsl:apply-templates select="name" />
      <xsl:apply-templates select="amount" />
      <xsl:apply-templates select="unit" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="function">
    <xsl:element name="function">
      <xsl:call-template name="copy-attributes"/>
      <xsl:apply-templates select="name" />
      <xsl:apply-templates select="quantification" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="unit">
    <xsl:element name="unit">
      <xsl:call-template name="copy-attributes"/>
      <xsl:apply-templates select="name" />
    </xsl:element>
  </xsl:template>

  <xsl:template name="copy-attributes"> 
    <xsl:for-each select="@*">
      <xsl:copy />
    </xsl:for-each>
  </xsl:template>

<!-- BELOW HERE ARE THE SPECIFIC TEMPLATES FOR REJOIN -->

  <xsl:template match="builtobject" mode="rejoin">
    <xsl:element name="builtobject">
      <xsl:call-template name="copy-attributes"/>
      <xsl:param name="target">
	<xsl:value-of select="string(./name)"/>
      </xsl:param>
      <!-- search in the tree for a builtobject with a builtobject
      parent in order *not* to find some builtobject with a
      characteristics parent... Then copy that builobject's names --> 
      <xsl:apply-templates
      select="//builtobject/builtobject[name=string($target)]" 
      mode="snatch" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="quantification" mode="rejoin">
    <xsl:element name="quantification">
      <xsl:call-template name="copy-attributes"/>
      <xsl:param name="target">
	<xsl:value-of select="string(./name)"/>
      </xsl:param>
      <!-- search for a quantification immediately below the cexml
      element with the correct name -->
      <xsl:apply-templates
      select="/cexml/quantification[name=string($target)]" 
      mode="snatch" />
      <xsl:apply-templates select="amount" />
      <xsl:apply-templates select="unit" mode="rejoin"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="function" mode="rejoin">
    <xsl:element name="function">
      <xsl:call-template name="copy-attributes"/>
      <xsl:param name="target">
	<xsl:value-of select="string(./name)"/>
      </xsl:param>
      <!-- search for a function immediately below the cexml
      element with the correct name -->
      <xsl:apply-templates
      select="/cexml/function[name=string($target)]" 
      mode="snatch" />
      <xsl:apply-templates select="quantification" mode="rejoin" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="unit" mode="rejoin">
    <xsl:element name="unit">
      <xsl:call-template name="copy-attributes"/>
      <xsl:param name="target">
	<xsl:value-of select="string(./name[1])"/>
      </xsl:param>
      <!-- search for a unit immediately below the cexml
      element with the correct name -->
      <xsl:apply-templates
      select="/cexml/unit[name=string($target)]" 
      mode="snatch" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="quantification" mode="snatch">
    <xsl:apply-templates select="name" />
  </xsl:template>
    
  <xsl:template match="function" mode="snatch">
    <xsl:apply-templates select="name" />
    <xsl:apply-templates select="quantification" mode="rejoin"/>
  </xsl:template>
    
  <xsl:template match="*" mode="snatch">
    <xsl:if test='not(self::node()[@mode="view"])'>
      <xsl:apply-templates select="name" />
    </xsl:if>
  </xsl:template>
    
</xsl:stylesheet>