The dfdl:discriminator syntax can only appear inside an 
<xs:annotation><xs:appinfo source="http://www.ogf.org/dfdl/";> block.

But it can appear on an element or on a sequence (or choice though that would 
be strange)

However, there's this perhaps unexpected thing about model groups 
(sequence/choice) and when statement-annotations (dfdl:discriminator, 
dfdl:assert, dfdl:setVariable,.... are statements) are actually evaluated. 
Section 9.6 of the DFDL specification talks about this. The order of evaluation 
actually differs depending on whether the discriminator uses testKind 'pattern' 
or testKind 'expression'.

<xs:sequence>
   <xs:annotation><xs:appinfo source="http://www.ogf.org/dfdl/";>
       <dfdl:discriminator>....test here </dfdl:discriminator>
   </xs:appnfo></xs:annotation>
   <xs:element name="foo" ..... />

</xs:sequence>

In that sequence, you'd typically think the discriminator would be evaluated 
and only if it is true would the element named "foo" be parsed. That's what 
happens if the discriminator uses testKind 'pattern'.

But.... for testKind 'expression' the annotation block for an xs:sequence is 
evaluated potentially as late as AFTER the sequence content. This is so that it 
can have an expression in it that examines the contents of the parsed sequence.

To get the above to mean "only parse the sequence body if the discriminator is 
true", you have to add another layer of sequence, so that the discriminator 
annotation is inside the first child of the sequence, and is an annotation on 
that INNER sequence:

<xs:sequence>
   <xs:sequence> <!-- inner sequence for discriminator -->
     <xs:annotation><xs:appinfo source="http://www.ogf.org/dfdl/";>
         <dfdl:discriminator>....test here </dfdl:discriminator>
     </xs:appnfo></xs:annotation>
   </xs:sequence>
   <xs:element name="foo" ..... />

</xs:sequence>

That forces it to do the right thing.

This is my preferred style for asserts and discriminators. Just always put them 
in their own sequence. That way if you cut/paste move them around, the meaning 
is what you normally think of when you look at the text ordering of the 
statements and elements. With this extra sequence wrapped around them, it also 
no longer matters what testKind they have.

-mikeb


________________________________
From: Patrick Grandjean <p.r.grandj...@gmail.com>
Sent: Saturday, June 20, 2020 9:40 AM
To: users@daffodil.apache.org <users@daffodil.apache.org>
Subject: Re: dfdl:choiceDispatchKey

Thank you Mike! It worked and explanation is very clear.

Can dfdl:discriminator be used as an attribute of a xs:element or only as a 
xs:annotation?

On Jun 18, 2020, at 4:11 PM, Beckerle, Mike 
<mbecke...@tresys.com<mailto:mbecke...@tresys.com>> wrote:

To use a pattern to discriminate a choice, you would use a dfdl:discriminator 
statement with testKind='pattern' on each branch of the choice. That assertion 
is using a regex to look at the data stream, and fails if the data stream at 
the current position doesn't start with a non-zero-length match of the pattern.

E.g., something like:

<xs:choice>
   <xs:sequence>
      <xs:annotation><xs:appinfo ...>
          <!-- Must begin with from 1 to 10 'a' characters -->
          <dfdl:discriminator testKind="pattern">a{1,10}</dfdl:discriminator>
      </xs:appinfo></xs:annotation>
      ... rest of 'a's branch...
   </xs:sequence>
   <xs:sequence>
      <xs:annotation><xs:appinfo ...>
          <!-- Must begin with from 1 to 10 'b' characters -->
          <dfdl:discriminator testKind="pattern">b{1,10}</dfdl:discriminator>
      </xs:appinfo></xs:annotation>
      ... rest of 'b's branch...
   </xs:sequence>
   ... other branches ...
</xs:choice>

Did that address your need?

One detail is that the matching of the discriminator pattern isn't consuming 
any data. When the branch is selected and parsing starts, you are still looking 
at the start of the data, not after the pattern matched. An element has to 
absorb these characters and then go on to parse the remainder of the branch. 
Sometimes that's easy, sometimes a slightly different idea makes more sense:

<xs:choice>
   <xs:sequence>
      <!--
       element that matches the pattern. If there is no match this will be 
zero-length string
        -->
      <xs:element name="aaBranchTag" type="xs:string"
            dfdl:lengthKind="pattern" dfdl:lengthPattern="a{1,10}"/>
      <xs:annotation><xs:appinfo ...>
          <!--
             if the match contains 1 or more characters, this is the right 
branch
           -->
          <dfdl:discriminator>{ fn:string-length(./aaBranchTag) gt 0 
}</dfdl:discriminator>
      </xs:appinfo></xs:annotation>
      ... rest of 'a's branch...starting from after the run of 'a's.
   </xs:sequence>
   .... other branches work similarly ....
</xs:choice>





________________________________
From: Patrick Grandjean 
<p.r.grandj...@gmail.com<mailto:p.r.grandj...@gmail.com>>
Sent: Thursday, June 18, 2020 3:28 PM
To: users@daffodil.apache.org<mailto:users@daffodil.apache.org> 
<users@daffodil.apache.org<mailto:users@daffodil.apache.org>>
Subject: dfdl:choiceDispatchKey

Hi!

I recently started using dfdl:choiceDispatchKey. According to the 
documentation, it only accepts DFDL expressions. Is it possible to use DFDL 
regular expressions instead? Or is there an alternative that would accept 
regexes?

Patrick.

Reply via email to