Menu

Sequence of choices

Help
2017-10-18
2017-10-18
  • Fabrice Salvaire

    Hi,

    MusicXML defines

    <xs:group name="music-data">
        <xs:annotation>
            <xs:documentation>The music-data group contains the basic musical data that is either associated with a part or a measure, depending on whether the partwise or timewise hierarchy is used.</xs:documentation>
        </xs:annotation>
        <xs:sequence>
            <xs:choice minOccurs="0" maxOccurs="unbounded">
                <xs:element name="note" type="note"/>
                <xs:element name="backup" type="backup"/>
                <xs:element name="forward" type="forward"/>
                <xs:element name="direction" type="direction"/>
                <xs:element name="attributes" type="attributes"/>
                <xs:element name="harmony" type="harmony"/>
                <xs:element name="figured-bass" type="figured-bass"/>
                <xs:element name="print" type="print"/>
                <xs:element name="sound" type="sound"/>
                <xs:element name="barline" type="barline"/>
                <xs:element name="grouping" type="grouping"/>
                <xs:element name="link" type="link"/>
                <xs:element name="bookmark" type="bookmark"/>
            </xs:choice>
        </xs:sequence>
    </xs:group>
    

    I read the section "Influencing Element and Mixed Content Order", but I don't understand how to keep the sequence order when I generate xml document "element.append(item)" don't keep the order.

    Other question, these elements are unamed despite "name"

    <xs:element name="score-timewise" block="extension substitution" final="#all">
        <xs:annotation>
            <xs:documentation>The score-timewise element is the root element for a timewise MusicXML score. It includes a score-header group followed by a series of measures with parts inside. The document-attributes attribute group includes the version attribute.</xs:documentation>
        </xs:annotation>
        <xs:complexType>
            <xs:sequence>
                <xs:group ref="score-header"/>
                <xs:element name="measure" maxOccurs="unbounded">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="part" maxOccurs="unbounded">
                                <xs:complexType>
                                    <xs:group ref="music-data"/>
                                    <xs:attributeGroup ref="part-attributes"/>
                                </xs:complexType>
                            </xs:element>
                        </xs:sequence>
                        <xs:attributeGroup ref="measure-attributes"/>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
            <xs:attributeGroup ref="document-attributes"/>
        </xs:complexType>
    </xs:element>
    
     
  • Peter A. Bigot

    Peter A. Bigot - 2017-10-19

    PyXB is concerned with validation, and the schema does not enforce an order. What support is provided was intended primarily for preserving order when processing existing documents, and your need to build them up manually may not be supported. For example, using this schema:

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:element name="SCn">
        <xs:complexType>
          <xs:sequence>
            <xs:choice minOccurs="0" maxOccurs="unbounded">
              <xs:element name="a" type="xs:integer"/>
              <xs:element name="b" type="xs:integer"/>
              <xs:element name="c" type="xs:integer"/>
              <xs:element name="d" type="xs:integer"/>
              <xs:element name="e" type="xs:integer"/>
              <xs:element name="f" type="xs:integer"/>
            </xs:choice>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:schema>
    

    with this test program:

    # -*- coding: utf-8 -*-
    
    import ts;
    import pyxb;
    
    tnc = '''
    <SCn>
        <c>1</c>
        <a>2</a>
        <b>3</b>
        <a>11</a>
        <c>12</c>
        <b>13</b>
    </SCn>
    '''
    
    scn = ts.CreateFromDocument(tnc);
    oc = scn.orderedContent();
    for elt in oc:
        print elt.elementDeclaration.name(), elt.value;
    print(scn.toDOM().toprettyxml());
    scn._validationConfig._setContentInfluencesGeneration(pyxb.GlobalValidationConfig.ALWAYS);
    print(scn.toDOM().toprettyxml());
    

    the result is:

    c 1
    a 2
    b 3
    a 11
    c 12
    b 13
    <?xml version="1.0" ?>
    <SCn>
        <a>2</a>
        <a>11</a>
        <b>3</b>
        <b>13</b>
        <c>1</c>
        <c>12</c>
    </SCn>
    
    <?xml version="1.0" ?>
    <SCn>
        <c>1</c>
        <a>2</a>
        <b>3</b>
        <a>11</a>
        <c>12</c>
        <b>13</b>
    </SCn>
    

    This shows the content provided by orderedContent() and the impact of setting the instance-specific validation configuration.

    This may not help in your case because you're building the document manually, and several ways of adding content are not detected and preserved in the built-up orderedContent() value. For example, if scn was constructed like this:

    scn = ts.SCn();
    scn.c.append(1);
    scn.a.append(2);
    scn.b.append(3);
    scn.a.append(11);
    scn.c.append(12);
    scn.b.append(13);
    

    the orderedContent() array would be empty and there would be no way to influence the generated order.

    For the other question those elements do have names, but they're visible only within the scope of the anonymous type that defines them. If you want to manipulate them as attributes you need to get an instance of the corresponding type first, which is tedious but necessary unless you can refactor the schema. See this section.

     

Log in to post a comment.