Thanks for the information. That makes things more clear.
The issue here is that with dfdl:occursCountKind="parsed", Daffodil
keeps parsing parameters until an error occurs (parse error, assertion
error, etc.). Such an error implies that we've found all of the
occurrences of the element, that the one it just tried and fail to parse
wasn't actually one of the occurrences. In this case, there are no more
elements to parse in the Paremeters element so it skips the remaining
bits of the fixed length Parameters element. This is called the "Unused
region". Since Daffodil just skips those bits, you do not get an error.
One thing we like to point out is the difference between "valid" data
and "well-formed" data. Sometimes the data is syntactically correct and
one would still be able to create a full infoset, but parts of the
infoset are things that are not "valid". For example the Record_Type is
4. Maybe a value of 4 meets the specification, but is just not
technically valid.
In this case, we often recommend that you parse the
well-formed/syntactically correct data, allowing invalid fields and an
infoest to be created. Then at the end you can perform validation on
that infoset to determine if what was parsed is valid or not. The
benefit here is that you can determine what actions to take on invalid
data. Maybe you fail it entirely, or maybe you just filter out the
invalid fields. If you always fail well-formed but invalid data, you do
not have that flexibility.
That said, if an invalid Result_Type really does mean the data is
not-well formed and you cannot continue to parse, or you do not want to
consider well-formed but invalid data, you can take the approach
described below.
By failing the assert, you are not telling Daffodil that the data is
wrong. You are just telling Daffodil that this was not an occurence of
the Parameters array. If you instead want to tell Daffodil that this
Record_Type was invalid error, you need to first tell Daffodil that this
was, in fact, an actual occurrence of the Parameters array using a
discriminator, and then perform the assert to tell Daffodil this
occurence was invalid. So something like this:
<xs:complexType name="parameters_record">
<xs:sequence>
<xs:element name="Record_Type" type="xs:short"/>
<xs:sequence>
<xs:annotation>
<xs:appinfo source="http://www.ogf.org/dfdl/">
<dfdl:discriminator test="{ fn:true() }"/>
</xs:appinfo>
</xs:annotation>
</xs:sequence>
<xs:sequence>
<xs:annotation>
<xs:appinfo source="http://www.ogf.org/dfdl/">
<dfdl:assert message="..." test="..."/>
</xs:appinfo>
</xs:annotation>
</xs:sequence>
...
</xs:sequence>
</xs:complexType>
If we fail to parse a Record_Type, it must have meant that we reach the
end of the fixed length Parameters element and things will work as
expected. However, if we successfully parse a Record_Type, that means
there was still some Parameter data available. So we then set a
discriminator to fn:true() to alert Daffodil to that we found another
occurrence of the Parameter array. Then we evaluate the assert. If that
assert fails, Daffodil will report it as an error because the
discriminator was set.
- Steve
On 5/31/19 3:47 PM, Kevin Moser wrote:
>
> Here is snippet of schema:
> ...
> <xs:element name="Parameters_Length" type="xs:int"/>
> <xs:choice dfdl:choiceDispatchKey="{ Parameters_Length eq 0 }">
> <xs:element name="Parameters_Empty" dfdl:choiceBranchKey"true"
> type="xs:hexBinary" dfdl:lengthUnits="bytes" dfdl:length="{0}"
> dfdl:lengthKind="explicit"/>
> <xs:element name="Parameters" dfdl:choiceBranchKey="false"
> dfdl:lengthKind="explicit" dfdl:length="{ ../Parameters_Length }">
> <xs:complexType>
> <xs:sequence>
> <xs:element name="Parameter" type="parameters_record"
> minOccurs="0" maxOccurs="unbounded" dfdl:occursCountKind="parsed"/>
> </xs:sequence>
> </xs:complexType>
> </xs:element>
> </xs:choice>
> ...
>
> <xs:complexType name="parameters_record">
> <xs:sequence>
> <xs:element name="Record_Type" type="xs:short"/>
> <xs:sequence>
> <xs:annotation>
> <xs:appinfo source="http://www.ogf.org/dfdl/">
> <dfdl:assert message="Only record types 1, 2, & 3 are
> allowed." test="{ Record_Type eq 1 or Record_Type eq 2 or Record_Type eq 3
> }"/>
> </xs:appinfo>
> </xs:annotation>
> </xs:sequence>
> ...
> </xs:sequence>
> </xs:complexType>
>
> When I send bad data containing an invalid setting for Record_Type (e.g., 5),
> the assert is not triggered and the xml output is produced.
>
> The xml output looks as follows:
> ...
> <Parameters_Length>16</Parameters_Length>
> <Parameters></Parameters>
>
> I need the assert to be triggered and error thrown.
>
> Thanks,
>
> Kevin
>
>
>
>
>
>
>
> On Fri, May 31, 2019 at 7:40 AM Steve Lawrence <[email protected]
> <mailto:[email protected]>> wrote:
>
> It's not 100% clear to me what behavior you are seeing and what you
> expect to see. Could you maybe provide a schema snippet of your complex
> and assert and what result you are looking for?
>
> - Steve
>
> On 5/30/19 3:49 PM, Kevin Moser wrote:
> > Another question related to this topic. During testing, we noticed
> that
> > dfdl:asserts were not failing (sending bad data to parser) if using
> "parsed".
> > The asserts are located within the parameter complex type to check if
> valid
> > record type. Any insight?
> >
> > On Tue, May 28, 2019, 3:14 PM Kevin Moser <[email protected]
> <mailto:[email protected]>
> > <mailto:[email protected] <mailto:[email protected]>>> wrote:
> >
> > Working on schema and am hoping to get some assistance on writing
> schema to
> > perform an iterative process. The protocol contains a length of
> parameters
> > field. It does not contain the number of parameters. I want to
> write the
> > schema to handle a variable number of parameters until the length
> of
> > parameters field is consumed (essentially a for loop or while
> loop). Any
> > suggestions?
> > Thanks, Kevin
> >
>