The DFDL spec says that all branches in an xs:choice must not have minOccurs '0' and if all branches are processed without a match then it is a processing error. But the DFDL spec also allows the creation of an empty xs:choice, that is, a choice without any branches at all.  Some questions arise:

1) What happens when choiceLengthKind is 'explicit' - SDE ? Insist that choiceLength is '0' ?

2) What happens if choiceBranchRef is specified ?

3) Assuming any syntax matches, an empty choice always parses successfully.  Read on...

I have been using an empty choice for modeling data formats where user-defined extensions are permitted.  This was the mechanism agreed upon by the WG to model this scenario in the absence of xs:any support in DFDL 1.0. Here's an example from a schema that models the TLOG retail format:

                            <xsd:choice>
                              <xsd:element ref="TransactionRecord00"/>
                            <xsd:element ref="TransactionRecord01"/>
                              <xsd:element ref="TransactionRecord04"/>
                              <xsd:element ref="TransactionRecord05"/>
                            <xsd:element ref="TransactionRecord98"/>
                            <xsd:group ref="choice_Custom"/>
                        </xsd:choice>


    <!-- Group for all user-defined records -->
    <xsd:group name="choice_Custom">
                <xsd:choice>        
                        <!-- Insert elements here -->
                                         
                 </xsd:choice>
    </xsd:group>

The intent is that the user adds his own records in the choice_Custom group. If an unknown record is parsed that fails to match any of the pre-defined records and any of the user-defined records, it will cause a processing error.

However that didn't actually work. Because choiceCustom is initially empty, it will parse successfully against any input and in doing so discriminate the outer choice, meaning the processing error is not thrown.  As soon as an element is added to choice_Custom, then it behaves as originally intended - an unknown record causes a processing error in choice_Custom, so the outer choice never discriminates.

To work around this I added an assert to the choice to ensure it fails when empty.

    <!-- Group for all user-defined records -->
    <xsd:group name="choice_Custom">
                <xsd:choice>        
                        <!-- Insert elements here -->
                                         
                        <!--  If we get here ensure choice fails -->
                        <xsd:sequence>
                                <xsd:annotation><xsd:appinfo source="http://www.ogf.org/dfdl/">
                                        <dfdl:assert>{fn:false()}</dfdl:assert>
                                </xsd:appinfo></xsd:annotation>
                        </xsd:sequence>
                 </xsd:choice>
    </xsd:group>

So is an empty choice a genuinely useful construct to allow? It didn't actually help my scenario in 3). Are there any where it would make sense?


Regards

Steve Hanson
Architect, Data Format Description Language (DFDL)
Co-Chair,
OGF DFDL Working Group
IBM SWG, Hursley, UK

smh@uk.ibm.com
tel:+44-1962-815848

Unless stated otherwise above:
IBM United Kingdom Limited - Registered in England and Wales with number 741598.
Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6 3AU