ly.xml package¶
Introduction¶
This package is concerned with representing a LilyPond structure (e.g. music) as an XML tree.
The structure of the tree closely follows LilyPond’s data structures. The tree can be parsed or analysed, and could be used to convert the music to other formats like Mei of MusicXML.
This package tries to define the exact format (dtd or schema) of the tree.
There will be three ways to build the tree:
by hand, by creating XML elements (maybe with use of some helper methods).
from a tokenized document
by LilyPond, using the
xml-export.ily
script that is included.
The latter case is very interesting as all the music parsing and handling is already done by LilyPond. The exported XML nearly contains all information of a score or music object. Below, some more information about the XML.
Note that this is all in heavy development.
Module contents¶
Routines that manipulate an XML mapping very similar to the Scheme music structure used by LilyPond itself.
The mapping can also be generated from within LilyPond and then parsed by other programs.
While designing the mapping, I decided to use xml elements for almost everything, only values that are very simple in all cases, are attributes.
Code could be written to convert such an XML music tree to other formats.
Also code is added to build such trees from scratch and from tokenized documents.
Code will be added to print LilyPond source. When all is finished, ly.dom is deprecated and ly.music will probably use these xml tree for storage.
A single LilyPond file xml-export.ily is also included with this module;
it can be included in a LilyPond document and exports the
\displayLilyXML
music function.
The xml-export.ily
file¶
Written by Wilbert Berendsen, jan-feb 2015
This LilyPond module defines a function (xml-export
) that converts LilyPond
datastructures to XML. For convenience, a \displayLilyXML
music function is
added that converts a music expression to XML.
Usage e.g.:
\include "/path/to/xml-export.ily"
\displayLilyXML { c d e f }
The XML closely follows the LilyPond music structure.
All (make-music 'MusicName ...)
objects translate to a
<music type="MusicName">
tag. The music in the 'element
and 'elements
properties is put in the <element>
and <elements>
tags. (LilyPond uses
'element
when there is a single music argument, and 'elements
for a list
of music arguments, but for example \repeat
uses both: 'element
for the
repeated music and 'elements
for the \alternatives
.)
Thus <element>
, if there, always has one <music>
child. <elements>
,
if there, can have more than one <music>
child.
Besides 'element
and 'elements
, the following properties of music
objects are handled specially:
'origin
=><origin>
element withfilename
,line
andchar
attributes'pitch
=><pitch>
element withoctave
,notename
andalteration
attributes'duration
=><duration>
element withlog
,dots
,numer
anddenom
attributes'articulations
=><articulations>
element containing<music>
elements'tweaks
=><tweaks>
element containing pairs(symbol . value)
All other properties a music object may have, are translated to a <property>
element with a name
attribute. The value is the child element and can be any
object (string, list, pair, symbol, number etc.). (Note that the LilyPond
command \displayMusic
does not display all properties.)
Markup objects are also converted to XML, where a toplevel <markup>
element
is used. The individual markup commands are converted to an <m>
element,
with the name in the name
attribute (e.g.
<m name="italic"><string value="Hi there!"/></m>
). Arguments to markup
commands may be other commands, or other objects (markup \score
even has
a score argument, which is also supported).
Example¶
This LilyPond music:
\relative {
c d e
}
maps to Scheme (using \displayMusic
):
(make-music
'RelativeOctaveMusic
'element
(make-music
'SequentialMusic
'elements
(list (make-music
'NoteEvent
'pitch
(ly:make-pitch -1 0 0)
'duration
(ly:make-duration 2 0 1))
(make-music
'NoteEvent
'pitch
(ly:make-pitch -1 1 0)
'duration
(ly:make-duration 2 0 1))
(make-music
'NoteEvent
'pitch
(ly:make-pitch -1 2 0)
'duration
(ly:make-duration 2 0 1)))))
and maps to XML (using \displayLilyXML
):
<music name="RelativeOctaveMusic">
<origin filename="/home/wilbert/dev/python-ly/ly/xml/xml-export.ily" line="244" char="17"/>
<element>
<music name="SequentialMusic">
<origin filename="/home/wilbert/dev/python-ly/ly/xml/xml-export.ily" line="244" char="27"/>
<elements>
<music name="NoteEvent">
<origin filename="/home/wilbert/dev/python-ly/ly/xml/xml-export.ily" line="245" char="4"/>
<pitch octave="-1" notename="0" alteration="0"/>
<duration log="2" dots="0" numer="1" denom="1"/>
</music>
<music name="NoteEvent">
<origin filename="/home/wilbert/dev/python-ly/ly/xml/xml-export.ily" line="245" char="6"/>
<pitch octave="-1" notename="1" alteration="0"/>
<duration log="2" dots="0" numer="1" denom="1"/>
</music>
<music name="NoteEvent">
<origin filename="/home/wilbert/dev/python-ly/ly/xml/xml-export.ily" line="245" char="8"/>
<pitch octave="-1" notename="2" alteration="0"/>
<duration log="2" dots="0" numer="1" denom="1"/>
</music>
</elements>
</music>
</element>
</music>
By default, the XML is written to standard output.
To automatically export a full LilyPond document to an XML representation,
use the xml-export-init.ly
script with the --init
LilyPond option.
That script automatically sets up LilyPond to output one XML document with a
<document>
root element, containing a <book>
element for every book
in the LilyPond file. (LilyPond always creates at least one book, collecting
all the music or markup at the toplevel.)
The xml-export-init.ly
script is intended to be used via the --init
option.
It automatically converts every \book
in the score to an XML document.
In this case the XML is also written to standard output by default, but you can
specify another file with -dxml-export=<filename>
.
So, to convert a LilyPond source file to an XML file containing the LilyPond music structure in XML format, use the following command:
lilypond --init /path/to/xml-export-init.ly -dxml-export=song.xml song.ly
The XML document has a <document>
root element, containing a <book>
element for every book in the LilyPond file.