https://github.com/apache/daffodil/pull/931
https://issues.apache.org/jira/browse/DAFFODIL-2562
https://issues.apache.org/jira/browse/DAFFODIL-2615

I've pounding my head against this issue for too long now, but I think I at 
least have a somewhat firm idea of what the problem is, just not how to fix it.


Schema for reference:

    <xs:group name="groupOfChoice">
      <xs:sequence>
        <xs:element name="key" type="xs:string" dfdl:lengthKind="explicit" 
dfdl:length="1" />
        <xs:choice dfdl:choiceDispatchKey="{ ./ex:key }">
          <xs:sequence dfdl:choiceBranchKey="a">
            <xs:element name="elt_a" type="xs:string" 
dfdl:lengthKind="explicit" dfdl:length="3" />
          </xs:sequence>
          <xs:sequence dfdl:choiceBranchKey="b">
            <xs:element name="elt_b" type="xs:string" 
dfdl:lengthKind="explicit" dfdl:length="3" />
            <xs:element name="elt_c" type="xs:string" 
dfdl:lengthKind="explicit" dfdl:length="3"
              minOccurs="0" maxOccurs="1" dfdl:occursCountKind="expression" 
dfdl:occursCount="{ if (fn:exists(../ex:elt_b)) then 1 else 0 }" />
          </xs:sequence>
        </xs:choice>
      </xs:sequence>
    </xs:group>

    <xs:element name="dd9">
      <xs:complexType>
        <xs:sequence>
          <xs:element name="prev" type="xs:string" dfdl:lengthKind="explicit" 
dfdl:length="1" />
          <xs:group ref="groupOfChoice" />
          <xs:element name="post" type="xs:string" dfdl:lengthKind="explicit" 
dfdl:length="1" />
        </xs:sequence>
      </xs:complexType>
    </xs:element>


As far as I can tell, everything gets set up correctly during the schema 
compile: PartialNextElementResolvers are created appropriately etc.  During 
runtime however, we are going through our infoset:

        <ex:dd9>
          <ex:prev>0</ex:prev>
          <ex:key>b</ex:key>
          <ex:elt_b>bbb</ex:elt_b>
          <ex:elt_c>ccc</ex:elt_c>
          <ex:post>1</ex:post>
        </ex:dd9>

So we go through the infoset and successfully unparse prev, key, and elt_b. We 
push elt_c onto the trdStack and it now looks like this:

trdStack: MStack(top=ex:elt_c, sequence[2], choice[2], group[2], sequence[1], 
element reference ex:dd9)

The PartialNextElementResolver successfully resolves elt_c, but since it is an 
optional element, it gets treated like an array and we end up calling 
state.inspect inside of RepeatingChildParser.shouldDoUnparser().  Inspect ends 
up advancing and asks what the nextElement is, which is "ex:post".  The issue 
is that we are just inspecting and the ex:post trd is never pushed onto the 
stack.  So, when we attempt to resolve element post, we check elt_c's resolver 
and fail, then check sequence[2] and fail, then check choice[2] where we get to 
the isRequiredStreamingUnparserEvent check in 
SeveralPossibilitiesForNextElement.maybeNextElement() and since all of 
choice[2]'s branches are Closed (correctly so I think) we determine that it is 
required.  So, when we try to find ex:post with choice[2]'s resolver we fail 
and instead of allowing things to continue, we instead return an 
UnexpecteElementErrorERD which brings everything to a halt essentially.

So, here is where I'm not sure what the correct solution is.

Should we not be calling inspect after we have already parsed the maximum 
allowed instances (1) of elt_c?

I don't think we should be pushing ex:post onto the stack at this point either, 
as later elt_c, sequence[2], choice[2], and group[2] get popped off the stack 
and post gets pushed on if we get past the UnexpectedElementErrorERD.

Is there a way to know that we are calling nextElement as a part of 
state.inspect and then not have it be required in 
SeveralPossibilitiesForNextElement?  I imagine this might cause other issues.

Let me know what you think.

Josh

Reply via email to