<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE xsl:stylesheet [
<!ENTITY startbeam      "&#xE501;">
<!ENTITY endbeam        "&#xE502;">
<!ENTITY % MusicChars SYSTEM
   'http://text.lib.virginia.edu/charent/musicchar.ent'> %MusicChars;
]>

<xsl:stylesheet
     version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:saxon="http://saxon.sf.net/"
     exclude-result-prefixes="saxon">

  <xsl:character-map name="music-chars">
    <xsl:output-character character="&#x1D110;" string="&amp;ferm;"/>
    <xsl:output-character character="&#x1D111;" string="&amp;fermbelow;"/>
    <xsl:output-character character="&#x1D1B8;" string="&amp;long;"/>
    <xsl:output-character character="&#x1D15C;" string="&amp;breve;"/>
    <xsl:output-character character="&#x1D15D;" string="&amp;note1;"/>
    <xsl:output-character character="&#x1D15E;" string="&amp;note2;"/>
    <xsl:output-character character="&#x1D15F;" string="&amp;note4;"/>
    <xsl:output-character character="&#x1D160;" string="&amp;note8;"/>
  </xsl:character-map>

  <xsl:character-map name="delimiters">
    <xsl:output-character character="&startbeam;" string="&lt;beam&gt;"/>
    <xsl:output-character character="&endbeam;" string="&lt;/beam&gt;"/>
  </xsl:character-map>

  <xsl:output method="xml" indent="no" encoding="UTF-8"
       omit-xml-declaration="no" standalone="no"
       doctype-system="http://www.lib.virginia.edu/digital/resndev/mei/mei17b/mei17b.dtd"
       use-character-maps="music-chars delimiters"/>

  <xsl:strip-space elements="*"/>

  <xsl:variable name="nl"><xsl:text>
</xsl:text>
  </xsl:variable>

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

  <!-- copy most elements and attributes -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:copy-of select="@*[not(name()='meiform') and not(name()='beam')]" />
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <!-- don't copy layer which contains only space -->
  <xsl:template match="layer[count(space)=count(*)]">
  </xsl:template>

  <!-- don't copy beam or staff attributes on space -->
  <xsl:template match="space">
    <xsl:copy>
      <xsl:copy-of select="@*[not(name()='meiform') and not(name()='beam') and not(name()='staff')]" />
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <!-- clean up def attributes on staff -->
  <xsl:template match="staff">
    <xsl:copy>
      <xsl:copy-of select="@*[not(name()='meiform') and not(name()='def')]"/>
      <xsl:choose>
        <xsl:when test="contains(@def,' ')">
          <xsl:attribute name="def">
            <xsl:value-of select="substring-before(@def,' ')"/>
          </xsl:attribute>
        </xsl:when>
        <xsl:otherwise>
          <xsl:copy-of select="@def"/>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <!-- copy attributes on staffdef elements preceding the first measure to corresponding
       top-level staffgrp/staffdef -->
  <xsl:template match="music/mdiv/score/scoredef[1]/staffgrp">
    <staffgrp>
      <xsl:apply-templates select="instrdef"/>
      <xsl:for-each select="staffdef|staffgrp">
        <xsl:choose>
          <xsl:when test="name()='staffdef'">
            <staffdef>
              <xsl:copy-of select="@*[not(name()='meiform')]"/>
              <xsl:variable name="thisstaff"><xsl:value-of select="@n"/></xsl:variable>
              <!-- Copy attributes from staffdef elements in section one -->
              <xsl:if test="following::section/staffdef[count(preceding::measure)=0]">
                <xsl:copy-of select="following::section[1]/staffdef[count(preceding::measure)=0 and
                                     @n=$thisstaff]/@*[not(name()='n') and not(name()='meiform')]"/>
              </xsl:if>
              <xsl:apply-templates select="*"/>
            </staffdef>
          </xsl:when>
          <xsl:when test="name()='staffgrp'">
            <staffgrp>
              <xsl:copy-of select="@*[not(name()='meiform')]"/>
              <xsl:apply-templates select="instrdef"/>
              <xsl:for-each select="staffdef">
                <staffdef>
                  <xsl:copy-of select="@*[not(name()='meiform')]"/>
                  <xsl:variable name="thisstaff"><xsl:value-of select="@n"/></xsl:variable>
                  <!-- Copy attributes from staffdef elements in section one -->
                  <xsl:if test="following::section[1]/staffdef[count(preceding::measure)=0]">
                    <xsl:copy-of select="following::section[1]/staffdef[count(preceding::measure)=0 and
                                         @n=$thisstaff]/@*[not(name()='n') and not(name()='meiform')]"/>
                  </xsl:if>
                  <xsl:apply-templates select="*"/>
                </staffdef>
              </xsl:for-each>
            </staffgrp>
          </xsl:when>
        </xsl:choose>
      </xsl:for-each>
      <xsl:apply-templates select="grpsym"/>
    </staffgrp>
  </xsl:template>

  <!-- copy staffdef elements and their attributes unless they precede the first measure -->
  <xsl:template match="section[1]/staffdef">
    <xsl:if test="not(count(preceding::measure)=0)">
      <xsl:copy>
        <xsl:copy-of select="@*[not(name()='meiform')]" />
        <xsl:apply-templates/>
      </xsl:copy>
    </xsl:if>
  </xsl:template>

  <!-- This template is only applied if the &startbeam and &endbeam entities have been
       serialized, i.e. only if this stylesheet is applied to *a file*. -->
  <!-- when beam contains only space children, copy the children, but not the beam.
       add with attribute on beam if necessary -->
  <xsl:template match="beam">
    <xsl:choose>
      <xsl:when test="count(space)=count(*)">
        <xsl:apply-templates/>
      </xsl:when>
      <xsl:otherwise>
        <beam>
          <xsl:choose>
            <xsl:when test="*[@staff &gt; ancestor::staff[1]/@def]">
              <xsl:attribute name="with">below</xsl:attribute>
            </xsl:when>
            <xsl:when test="*[@staff &lt; ancestor::staff[1]/@def]">
              <xsl:attribute name="with">above</xsl:attribute>
            </xsl:when>
          </xsl:choose>
          <xsl:copy-of select="@*[not(name()='meiform')]"/>
          <xsl:apply-templates/>
        </beam>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>
