[xsd-users] Preserving element order in MusicXML?
Boris Kolpackov
boris at codesynthesis.com
Wed May 28 10:03:55 EDT 2008
Hi Mario,
Mario Lang <mlang at delysid.org> writes:
> <measure>
> <attributes>...</attributess>
> <note>...</note><note>...</note>
> <note>...</note><note>...</note>
> <backup>...</backup>
> <attributes>...</attributes>
> <note>...</note>
> </measure>
>
> would be a valid MusicXML snippet.
>
> Currently, after xsdcxx serialisation of the above snippet, I get
> sonmething like:
>
> <measure>
> <note>...</note><note>...</note>
> <note>...</note><note>...</note>
> <note>...</note>
> <backup>...</backup>
> <attributes>...</attributess>
> <attributes>...</attributes>
> </measure>
>
> which is completely wrong in MusicXML context, since the elements
> can be thought of like statements in a procedural program, they
> depend on the order of things being preserved.
>
> [...]
>
> I am beginning to suspect that this is actually a XML Schema limitation
> or a limitation in xsdcxx that I am hitting here.
This is a limitation of the C++/Tree mapping and it was a conscious
trade-off between ease of use and being able to retain certain
information that is sometimes required (like order). In essence,
C++/Tree mapping flattens the schema model and groups several
occurrences of the same element into a sequence. This works quite
well for data-centric XML vocabularies but sometimes is insufficient
for document-centric ones like XHTML or MusicXML.
There is another mapping, C++/Parser, that by design allows you
to capture the order information. It is, however, only supports
parsing (the serialization-supporting counterpart, C++/Serializer,
is on its way).
> <xs:complexType name="music-data">
> <xs:sequence>
> <xs:choice minOccurs="0" maxOccurs="unbounded">
> <xs:element ref="note" minOccurs="0" maxOccurs="unbounded"/>
> <xs:element ref="backup" minOccurs="0" maxOccurs="unbounded"/>
> <xs:element ref="forward" minOccurs="0" maxOccurs="unbounded"/>
> <xs:element ref="direction" minOccurs="0" maxOccurs="unbounded"/>
> <xs:element ref="attributes" minOccurs="0" maxOccurs="unbounded"/>
> <xs:element ref="harmony" minOccurs="0" maxOccurs="unbounded"/>
> <xs:element ref="figured-bass" minOccurs="0" maxOccurs="unbounded"/>
> <xs:element ref="print" minOccurs="0" maxOccurs="unbounded"/>
> <xs:element ref="sound" minOccurs="0" maxOccurs="unbounded"/>
> <xs:element ref="barline" minOccurs="0" maxOccurs="unbounded"/>
> <xs:element ref="grouping" minOccurs="0" maxOccurs="unbounded"/>
> <xs:element ref="link" minOccurs="0" maxOccurs="unbounded"/>
> <xs:element ref="bookmark" minOccurs="0" maxOccurs="unbounded"/>
> </xs:choice>
> </xs:sequence>
> </xs:complexType>
> <xs:element name="measure" type="music-data"/>
>
>
> Is it possible to express a schema for sturcture like above and
> use it with xsdcxx? If so, what am I missing?
Since you have control over the schema, I can propose an elegant
workaround which will allow you to retain order and use the C++/Tree
mapping. It boils down to using XML Schema substitution groups to
represent various music data elements. Here is an outline:
<xs:complexType name="music-element" abstract="true">
<!-- Here you may want to put common data that each music
element must have, if any. -->
</xs:complexType>
<xs:element name="music-element" type="music-element" abstract="true"/>
<xs:complexType name="music-data">
<xs:sequence>
<xs:element ref="music-element" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="measure" type="music-data"/>
<!-- define backup, forward, etc., in the same way: -->
<xs:complexType name="note">
<xs:complexContent>
<xs:extension base="music-element">
<xs:sequence>
...
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="note" type="note" substitutionGroup="music-element"/>
In the OOP terms the above schema says that the music-data type
contains a sequence of abstract music-element elements each of which
can be note, backup, forward, etc.
Once you compile this schema with the --generate-polymorphic option,
you will get a "polymorphic sequence" of music-element items in
the music-data type. While the static type in this sequence is
music-element, actual objects stored are note, backup, etc. You
can figure out which object it is by using, for example, dynamic_cast.
For more information on working with polymorphic object models
see Section 2.11, "Mapping for xsi:type and Substitution Groups"
in the C++/Tree Mapping Manual:
http://codesynthesis.com/projects/xsd/documentation/cxx/tree/manual/#2.11
Boris
More information about the xsd-users
mailing list