--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 2.0 Partwise//EN" "http://www.musicxml.org/dtds/partwise.dtd">
+<score-partwise version="2.0">
+ <identification>
+ <miscellaneous>
+ <miscellaneous-field name="description">A part with no id attribute.
+ Since this piece has only one part, it is clear which part
+ is described by the one part element.</miscellaneous-field>
+ </miscellaneous>
+ </identification>
+ <part-list>
+ <score-part id="P1">
+ <part-name print-object="no">MusicXML Part</part-name>
+ </score-part>
+ </part-list>
+ <part>
+ <measure number="1">
+ <note>
+ <rest/>
+ <duration>4</duration>
+ <voice>1</voice>
+ <type>whole</type>
+ </note>
+ </measure>
+ </part>
+</score-partwise>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 2.0 Partwise//EN" "http://www.musicxml.org/dtds/partwise.dtd">
+<score-partwise version="2.0">
+ <identification>
+ <miscellaneous>
+ <miscellaneous-field name="description">This piece has more part elements
+ than the part-list section gives. One can either convert all
+ the parts present, but not listed in the part-list, or simply
+ not import / ignore them.</miscellaneous-field>
+ </miscellaneous>
+ </identification>
+ <part-list>
+ <score-part id="P1">
+ <part-name print-object="no">MusicXML Part</part-name>
+ </score-part>
+ </part-list>
+ <part id="P1">
+ <measure number="1">
+ <note>
+ <rest/>
+ <duration>4</duration>
+ <voice>1</voice>
+ <type>whole</type>
+ </note>
+ </measure>
+ </part>
+ <part id="P3">
+ <measure number="1">
+ <note>
+ <rest/>
+ <duration>4</duration>
+ <voice>1</voice>
+ <type>whole</type>
+ </note>
+ </measure>
+ </part>
+ <part id="P4">
+ <measure number="1">
+ <note>
+ <rest/>
+ <duration>4</duration>
+ <voice>1</voice>
+ <type>whole</type>
+ </note>
+ </measure>
+ </part>
+</score-partwise>
def voices_in_part_in_parts (parts):
"""return a Part -> Name -> Voice dictionary"""
- return dict([(p.id, voices_in_part (p)) for p in parts])
+ # don't crash if p doesn't have an id (that's invalid MusicXML,
+ # but such files are out in the wild!
+ dictionary = {}
+ for p in parts:
+ voices = voices_in_part (p)
+ if (hasattr (p, "id")):
+ dictionary[p.id] = voices
+ else:
+ # TODO: extract correct part id from other sources
+ dictionary[None] = voices
+ return dictionary;
def get_all_voices (parts):