I’d like to discuss this example in email and/or on
our call this week. It illustrates that discriminators must be evaluated both
on output and on input. We proposed at the F2F that assertions are only about
parsing, but the same cannot be said of discriminators.
Because email often line-wraps in ways that break things I’ve
also attached the same example as a file.
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- 80 column ruler
2345678901234567890123456789012345678901234567890123456 -->
<!--
***************************************************************************
********************************************************************************
Illustration of use of layering with choices and
discrimintors
Lessons from this example:
Discriminators must be evaluated on output as well
as input in order to decide
choices.
********************************************************************************
***************************************************************************
-->
<xs:schema
targetNamespace="http://dataformat.org/tests"
elementFormDefault="qualified"
xsi:schemaLocation=
"http://www.ogf.org/dfdl/dfdl-0.1 ../../xsd/dfdl.xsd
http://www.w3.org/2001/XMLSchema ../../xsd/XMLSchema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.ogf.org/dfdl/tests"
xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-0.1">
<!--
*************************************************************************
Our default format will be binary, without
delimiters, with bits for alignment
units, and implicit length kind which we'll override
where needed.
*************************************************************************
-->
<xs:annotation><xs:appinfo
source="http://www.ogf.org/dfdl/dfdl-0.1">
<dfdl:defineFormat name="default">
<dfdl:format
representation="binary"
lengthKind="implcit" initiator="" separator=""
terminator=""
alignmentUnits="bits"
/>
</dfdl:defineFormat>
</xs:appinfo></xs:annotation>
<!-- *************************************************************************
Example: a string with smart one byte or four byte
length preceding it.
Modeled as a single bit flag, followed by a 7 bit or
31 bit integer after it.
*************************************************************************
-->
<xs:complexType
name="smartLengthString" dfdl:ref="default"
dfdl:lengthKind="explicit" dfdl:lengthUnits="bits">
<xs:sequence>
<xs:annotation><xs:appinfo source="...">
<dfdl:hidden>
<xs:element
name="lengthFlag" type="xs:byte"
dfdl:length="1"
dfdl:alignment="8"
dfdl:outputValueCalc='{
if ( ../logicalLength > 127 ) then "1" else "0"
}'
/>
<xs:choice
dfdl:choiceKind='variable' dfdl:choiceResolvable="true">
<!-- First
choice alternative: one byte -->
<xs:sequence>
<xs:annotation><xs:appinfo
source="http://www.ogf.org/dfdl/dfdl-0.1">
<dfdl:discriminator test="{ ../lengthFlag != '1' }"
/>
</xs:appinfo></xs:annotation>
<xs:element name="oneByte" type="xs:byte"
dfdl:alignment="1"
dfdl:length="7"
dfdl:outputValueCalc="{ ../logicalLength }" />
</xs:sequence>
<!-- Second
choice alternative: one byte -->
<xs:element
name="fourByte" type="xs:int"
dfdl:alignment="1"
dfdl:length="31"
dfdl:outputValueCalc="{ ../logicalLength }" />
</xs:choice>
<!--
this logicalLength element below isn't strictly speaking needed in this
example. It's here to illustrate something having both input and output
value calculation, and makes things a bit more readable.
-->
<xs:element
name="logicalLength" type="xs:int"
dfdl:inputValueCalc="{
if (../lengthFlag = '1') then ../fourByte else ../oneByte
}"
dfdl:outputValueCalc= "{
dfdl:length(../str, 'characters')
}"
/>
</dfdl:hidden>
</xs:appinfo></xs:annotation>
<xs:annotation><xs:appinfo source="...">
<xs:element
name="str" type="xs:string"
dfdl:length="{ ../logicalLength }"
dfdl:lengthUnits="characters" />
</xs:sequence>
</xs:complexType>
</xs:schema>