to31.xsl
<?xml version="1.0" encoding="UTF-8"?> <!-- MusicXML to31.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/ --> <!-- To31.xsl converts from MusicXML 4.0 to 3.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 3.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-3.1 elements and attributes. --> <!-- Additions in note.mod --> <!-- Remove new elements. --> <xsl:template match="listen"/> <!-- Remove all but the first instrument element --> <xsl:template match="instrument[position() > 1]"/> <!-- Remove accidental SMuFL attributes with new values. --> <xsl:template match="accidental/@smufl[not(starts-with(., 'acc'))]"/> <!-- Remove elements with number attributes greater than 6. --> <xsl:template match="arpeggiate[number(@number) > 6] | glissando[number(@number) > 6] | hammer-on[number(@number) > 6] | non-arpeggiate[number(@number) > 6] | other-notation[number(@number) > 6] | pull-off[number(@number) > 6] | slide[number(@number) > 6] | slur[number(@number) > 6] | tied[number(@number) > 6] | tuplet[number(@number) > 6]"/> <!-- Remove new attributes. --> <xsl:template match="arpeggiate/@unbroken | bend/@shape | figured-bass/@halign | figured-bass/@valign | figured-bass/@placement | release/@offset"/> <!-- Additions in attributes.mod --> <!-- Remove double elements that have an above value other than no, then remove the above attribute altogether. Make sure the tests have the right priority so the doubles are removed first, before the above attribute is removed. --> <xsl:template match="double/@above"/> <xsl:template priority="1" match="double[@above != 'no']"/> <!-- Remove new elements. --> <xsl:template match="for-part | line-detail"/> <!-- Remove new attributes. --> <xsl:template match="staff-size/@scaling"/> <!-- Additions in barline.mod --> <!-- Remove new attributes. --> <xsl:template match="ending/@system | repeat/@after-jump"/> <!-- Additions in common.mod --> <!-- Remove level elements that have a type other than single, then remove the type attribute altogether. Make sure the tests have the right priority so the levels are removed first, before the type attribute is removed. --> <xsl:template match="level/@type"/> <xsl:template priority="1" match="level[@type != 'single']"/> <!-- Remove enclosure attributes with inverted-bracket value. --> <xsl:template match="@enclosure[. = 'inverted-bracket']"/> <!-- Remove elements with number attributes greater than 6. --> <xsl:template priority="1" match="wavy-line[number(@number) > 6]"/> <!-- Remove new attributes. --> <xsl:template match="wavy-line/@smufl"/> <!-- Additions in direction.mod --> <!-- Convert discontinue pedal types to stop pedal types, and resume pedal types to start pedal types. We do this instead of removing the entire element so that we do not leave dangling pedal elements after the conversion. --> <xsl:template match="pedal/@type[. = 'discontinue']"> <xsl:attribute name="type">stop</xsl:attribute> </xsl:template> <xsl:template match="pedal/@type[. = 'resume']"> <xsl:attribute name="type">start</xsl:attribute> </xsl:template> <!-- Remove entire harmony that has a new numeral child element. --> <xsl:template match="harmony[numeral]"/> <!-- Remove elements with number attributes greater than 6. --> <xsl:template match="direction[direction-type/bracket[number(@number) > 6]] | direction[direction-type/dashes[number(@number) > 6]] | direction[direction-type/octave-shift[number(@number) > 6]] | direction[direction-type/pedal[number(@number) > 6]] | direction[direction-type/wedge[number(@number) > 6]]"/> <!-- Remove new elements. --> <xsl:template match="bass-separator | instrument-change | listening | swing"/> <!-- Remove new attributes. --> <xsl:template match="direction/@system | harmony/@system | harmony/@arrangement | bass/@arrangement | inversion/@text | metronome/@print-object | measure-numbering/@system | measure-numbering/@staff | measure-numbering/@multiple-rest-always | measure-numbering/@multiple-rest-range | effect/@smufl | membrane/@smufl | metal/@smufl | timpani/@smufl | wood/@smufl"/> <!-- Additions in score.mod --> <!-- Remove new elements. --> <xsl:template match="concert-score | part-link | player"/> <!-- Convert score version attribute to 3.1. --> <xsl:template match="score-partwise/@version"> <xsl:attribute name="version">3.1</xsl:attribute> </xsl:template> <!-- The identity transformation. Used for everything that stays the same in 3.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>