to11.xsl

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

<!--
  MusicXML to11.xsl stylesheet

  Version 4.0

  Copyright © 2004-2021 the Contributors to the MusicXML 
  Specification, published by the W3C Music Notation Community
  Group under the W3C Community Final Specification Agreement 
  (FSA): 

     https://www.w3.org/community/about/agreements/final/

  A human-readable summary is available:

     https://www.w3.org/community/about/agreements/fsa-deed/
-->

<!--
  To11.xsl converts from MusicXML 2.0 to 1.1 for
  compatibility with older products.
-->

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  
  <!--
    XML output, with a DOCTYPE referring the partwise DTD.
    Here we use the full Internet URL.
  -->
  
  <xsl:output method="xml" indent="yes" encoding="UTF-8"
    omit-xml-declaration="no" standalone="no"
    doctype-system="http://www.musicxml.org/dtds/partwise.dtd"
    doctype-public="-//Recordare//DTD MusicXML 1.1 Partwise//EN"/>
  
  <!--
    For the root, only look for score-partwise. Anything else 
    as a root element gets ignored.
  -->  
  <xsl:template match="/">
    <xsl:apply-templates select="./score-partwise"/>
  </xsl:template>
  
  <!--
    Transformations that remove post-1.1 elements and 
    attributes.
  -->
  
  <!-- Additions in note.mod -->
  <xsl:template 
    match="dot/@placement | tremolo/@type |
    harmonic/@print-object | 
    other-notation/@print-object |
    stress | unstress | inverted-turn | 
    pluck/text() | elision/text()"/>
  
  <!--
    If there is no elision element, remove all but the first
    text and syllabic elements.
  -->  
  <xsl:template 
    match="lyric[not (elision)]/text[position() > 1] |
    lyric[not (elision)]/syllabic[position() > 1]"/>
  
  <!-- Remove other-notation elements with a single type. -->
  <xsl:template 
    match="other-notation[@type = 'single']"/>
  
  <!-- Additions in attributes.mod -->
  <xsl:template 
    match="key/@font-family | key/@font-style |
    key/@font-size | key/@font-weight |
    key/@default-x | key/@default-y |
    key/@relative-x | key/@relative-y |
    time/@font-family | time/@font-style |
    time/@font-size | time/@font-weight |
    time/@default-x | time/@default-y |
    time/@relative-x | time/@relative-y |
    clef/@font-family | clef/@font-style |
    clef/@font-size | clef/@font-weight |
    clef/@default-x | clef/@default-y |
    clef/@relative-x | clef/@relative-y | clef/@size |
    key/@print-object | clef/@print-object |
    cancel/@location | part-symbol | key-octave |
    slash-type | slash-dot"/>
  
  <!-- Remove additional clefs altogether -->
  <xsl:template 
    match="clef[@additional]"/>
  
  <!-- Remove all but first key and time element -->
  <xsl:template 
    match="attributes/key[position() > 1] | 
    attributes/time[position() > 1]"/>
  
  <!-- Additions in barline.mod -->
  <xsl:template 
    match="ending/@print-object | ending/@text-x |
    ending/@text-y | barline/@segno |
    barline/@coda | barline/@divisions"/>
  
  <xsl:template 
    match="bar-style[(. = 'tick') or (. = 'short')]"/>
  
  <!-- Additions in common.mod -->
  <xsl:template 
    match="volume | pan | elevation | @directive |
    part-name-display | part-abbreviation-display | 
    @rotation | @dir | @letter-spacing | @line-height |
    @overline | @underline | @line-through |
    footnote/@xml:lang | footnote/@enclosure |
    fermata/text()"/>
  
  <!-- Additions in identity.mod -->
  <xsl:template 
    match="relation"/>
  
  <!--
    Remove a supports element that contains an attribute or
    value attribute
  -->
  <xsl:template 
    match="supports[@attribute | @value]"/>
  
  <!-- Additions in layout.mod -->
  <xsl:template 
    match="appearance"/>
  
  <!-- 
    Remove a page-layout element that does not have a
    page-height child
  -->
  <xsl:template 
    match="page-layout[not (page-height)]"/>
  
  <!-- Additions in direction.mod -->
  <xsl:template 
    match="offset/@sound | sound/offset |
    measure-numbering | print/@blank-page |
    print/part-name | print/part-abbreviation |
    root-step/@* | root-alter/@* |
    bass-step/@* | bass-alter/@* |
    function/@* | inversion/@* | 
    kind/@default-x | kind/@default-y |
    kind/@relative-x | kind/@relative-y |
    kind/@font-family | kind/@font-style |
    kind/@font-size | kind/@font-weight | 
    kind/@color | kind/@halign | kind/@valign |
    degree-value/@* | degree-alter/@* | 
    degree-type/@* | per-minute/@* |
    frame/@halign | frame/@valign |
    first-fret/@* | other-direction/@print-object"/>
  
  <!-- 
    For safety, remove entire direction that has a new
    MusicXML 2.0 direction-type child, or a new style
    of metronome element.
  -->
  <xsl:template 
    match="direction[direction-type[image]]"/>
  
  <xsl:template 
    match="direction[direction-type[accordion-registration]]"/>
  
  <xsl:template 
    match="direction[direction-type[metronome[metronome-note]]]"/>
  
  <!-- 
    Remove pedal attributes that have values other than 
    yes or no.
  -->
  <xsl:template 
    match="@damper-pedal[. != 'yes' and . != 'no'] "/>
  <xsl:template 
    match="@soft-pedal[. != 'yes' and . != 'no'] "/>
  <xsl:template 
    match="@sostenuto-pedal[. != 'yes' and . != 'no'] "/>
  
  <!-- 
    Remove grouping type attributes that have values other than 
    start or stop.
  -->
  <xsl:template 
    match="grouping/@typel[. != 'start' and . != 'stop'] "/>
  
  <!-- Additions in link.mod -->
  <xsl:template 
    match="link/@element | link/@position | 
    bookmark/@element | bookmark/@position"/>
  
  <!-- Additions in score.mod -->
  <xsl:template 
    match="group-name-display | group-abbreviation-display |
    group-time | solo | ensemble | credit[credit-image] |
    credit/link | credit/bookmark"/>
  
  <!-- Remove a credit that is not on page 1 -->
  <xsl:template 
    match="credit[@page != '1']"/>
  
  <!-- Remove the page attribute for page 1 credits -->
  <xsl:template 
    match="credit/@page[. = '1']"/>
  
  <!--
    Convert score version attribute to 1.1
  -->
  <xsl:template 
    match="score-partwise/@version">
    <xsl:attribute name="version">1.1</xsl:attribute>
  </xsl:template>
  
  <!--
    Do not copy text for elision, pluck, or fermata elements.
  -->
  <xsl:template match="elision | pluck | fermata">
    <xsl:copy><xsl:apply-templates
      select="*|@*|comment()|processing-instruction()"
    /></xsl:copy>
  </xsl:template>
  
  <!--
    The identity transformation. Used for everything that
    stays the same in 1.1.
  -->
  
  <xsl:template match="text()">
    <xsl:value-of select="." />
  </xsl:template>
  
  <!--
    Whitespace within an xsl:copy could cause problems with 
    empty elements.
  -->
  <xsl:template match="*|@*|comment()|processing-instruction()">
    <xsl:copy><xsl:apply-templates
      select="*|@*|comment()|processing-instruction()|text()"
    /></xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>