You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@daffodil.apache.org by Christofer Dutz <ch...@c-ware.de> on 2019/05/07 07:40:37 UTC
What is the right way to define constants?
Hi,
in our PLC4X project we have several places where there are bytes with fixed values expected.
How would be the right was to define that?
So a S7 protocol message would always start with a byte with the value 0x32 … simply modeling that as a byte would make a packet with 0x42 also valid, which is not the case.
So how do I force the byte value to be exactly a pre-defined value?
Chris
Re: What is the right way to define constants?
Posted by Christofer Dutz <ch...@c-ware.de>.
Ah ok ... thanks for those infos ...
Guess I had things almost right from the start as I was using fixed, but thought it didn't apply as it was still succeeding __
I'll let those infos flow into my schemas.
Thanks,
Chris
Am 07.05.19, 13:49 schrieb "Steve Lawrence" <sl...@apache.org>:
There's a couple ways to do this in DFDL.
One way is with the XSD "fixed" facet. So something like:
<xs:element name="field" type="xs:byte" fixed="50" ... />
The fixed attribute is only checked when validation is enabled. If so,
and "field" does not match the value of the fixed facet, parsing will
still continue as normal, but validation errors will be reported at the
end of parsing. The benefit of this is that if "field" isn't valid with
respect to the facet, you will still get an infoset. So if everything
else about the data is correct and "well-formed" but not valid, you can
potentially recover. Unfortunately, Daffodil does not support this facet
yet (DAFFODIL-117). But you can achieve the same functionality using
xs:restriction:
<xs:element name="field" ...>
<xs:simpleType>
<xs:restriction type="xs:byte">
<xs:minInclusive value="50" />
<xs:maxInclusive value="50" />
</xs:restriction>
</xs:simpleType>
</xs:element>
This is essentially the same thing as using fixed, just not as concise.
A different method with a different behavior is to use dfdl:assert to
check the value after it has been parsed:
<xs:element name="field" type="xs:byte" ...>
<xs:annotation>
<xs:appinfo source="http://www.ogf.org/dfdl/">
<dfdl:assert test="{ . eq 50 }" />
</xs:appinfo>
</xs:annotation>
</xs:element>
In this case, the assert test is performed at parse time immediately
after field is parsed. If field is not the correct value, the failed
assert will immediately result in an ParseError and Daffodil will
backtrack, which could lead to a parse failure and no infoset. If you
want the parse to fail when fields are invalid, this is the route to take.
Also, note that assertions are not checked when unparsing--Daffodil will
just unparse whatever value is in the infoset. If you also want to
ensure the value is constant on unparsing, you can either manually
modify the infoset before unparsing if it's not the right value, or use
dfdl:outputValueCalc to have Daffodil unparse a different value than
what is in the infoset:
<xs:element name="field" type="xs:byte" dfdl:outputValueCalc="{ 50 }"
... />
- Steve
On 5/7/19 3:40 AM, Christofer Dutz wrote:
> Hi,
>
> in our PLC4X project we have several places where there are bytes with fixed
> values expected.
>
> How would be the right was to define that?
>
> So a S7 protocol message would always start with a byte with the value 0x32 …
> simply modeling that as a byte would make a packet with 0x42 also valid, which
> is not the case.
>
> So how do I force the byte value to be exactly a pre-defined value?
>
> Chris
>
Re: What is the right way to define constants?
Posted by Steve Lawrence <sl...@apache.org>.
There's a couple ways to do this in DFDL.
One way is with the XSD "fixed" facet. So something like:
<xs:element name="field" type="xs:byte" fixed="50" ... />
The fixed attribute is only checked when validation is enabled. If so,
and "field" does not match the value of the fixed facet, parsing will
still continue as normal, but validation errors will be reported at the
end of parsing. The benefit of this is that if "field" isn't valid with
respect to the facet, you will still get an infoset. So if everything
else about the data is correct and "well-formed" but not valid, you can
potentially recover. Unfortunately, Daffodil does not support this facet
yet (DAFFODIL-117). But you can achieve the same functionality using
xs:restriction:
<xs:element name="field" ...>
<xs:simpleType>
<xs:restriction type="xs:byte">
<xs:minInclusive value="50" />
<xs:maxInclusive value="50" />
</xs:restriction>
</xs:simpleType>
</xs:element>
This is essentially the same thing as using fixed, just not as concise.
A different method with a different behavior is to use dfdl:assert to
check the value after it has been parsed:
<xs:element name="field" type="xs:byte" ...>
<xs:annotation>
<xs:appinfo source="http://www.ogf.org/dfdl/">
<dfdl:assert test="{ . eq 50 }" />
</xs:appinfo>
</xs:annotation>
</xs:element>
In this case, the assert test is performed at parse time immediately
after field is parsed. If field is not the correct value, the failed
assert will immediately result in an ParseError and Daffodil will
backtrack, which could lead to a parse failure and no infoset. If you
want the parse to fail when fields are invalid, this is the route to take.
Also, note that assertions are not checked when unparsing--Daffodil will
just unparse whatever value is in the infoset. If you also want to
ensure the value is constant on unparsing, you can either manually
modify the infoset before unparsing if it's not the right value, or use
dfdl:outputValueCalc to have Daffodil unparse a different value than
what is in the infoset:
<xs:element name="field" type="xs:byte" dfdl:outputValueCalc="{ 50 }"
... />
- Steve
On 5/7/19 3:40 AM, Christofer Dutz wrote:
> Hi,
>
> in our PLC4X project we have several places where there are bytes with fixed
> values expected.
>
> How would be the right was to define that?
>
> So a S7 protocol message would always start with a byte with the value 0x32 …
> simply modeling that as a byte would make a packet with 0x42 also valid, which
> is not the case.
>
> So how do I force the byte value to be exactly a pre-defined value?
>
> Chris
>