枚举二进制数据的 DFDL 解码



我目前正在为系统中使用的传统(自定义(二进制文件格式研究DFDL模式,以转换为XML或JSON。

我有一些枚举值的二进制数据,即 C 结构数据类型如下所示(并存储为字节(:

typedef enum _SomeEnum
{
ENUM_1 = 0x00,
ENUM_2 = 0x01,
ENUM_3 = 0x02
} SomeEnum;

我可以使用此 DFDL 模式代码(包括检查(将枚举解码为数值:

<xs:element name="SomeEnum" type="xs:unsignedByte>
<xs:annotation>
<xs:appinfo source="http://www.ogf.org/dfdl/">
<dfdl:assert><![CDATA[{ . lt 3 }]]></dfdl:assert>
</xs:appinfo>
</xs:annotation>
</xs:element>

在这种情况下,它转换为枚举字段等于 1 的 XML:

<SomeEnum>1</SomeEnum>

我想要的是能够将解码的枚举值转换为字符串,以便XML结果如下所示:

<SomeEnum>ENUM_1</SomeEnum>

但我不确定如何使用 DFDL 做到这一点。

我正在使用Daffodil作为我的DFDL解析器/处理器(尽管我怀疑IBM集成总线DFDL解析器也能够做到这一点(

免责声明,我是实现以下选项 2 的水仙花开发人员。

我不相信IBM DFDL有很好的解决方案来解决这个问题。

水仙花提供2种解决方案:

1( 使用 inputValueCalc/outputValueCalc。这里的理论是,你首先将枚举解析为一个整数(可能在隐藏组中(,然后使用 DFDL 表达式在一个大的 if-else 语句中计算友好的字符串:

<xs:group name="enum">
<xs:sequence>
<xs:element name="enum_int" type="xs:int" dfdl:length="1" dfdl:outputValueCalc="{if (../SomeEnum eq 'ENUM_1') then 0 else if (../SomeEnum eq 'ENUM_2') then 1 else if (../SomeEnum eq 'ENUM_3') then 2 else fn:error()}"/>
</xs:sequence>
</xs:group>
<xs:sequence>
<xs:sequence dfdl:hiddenGroupRef="tns:enum"/>
<xs:element name="SomeEnum" dfdl:inputValueCalc="if(../enum eq 0) then 'ENUM_1' else if(../enum eq 1) then 'ENUM_2' else if(../enum eq 2) then 'ENUM_3' else fn:error()" />
<xs:sequence>

这种方法的好处是完全符合 DFDL。缺点是它很快就会变得笨拙,对于大型枚举(维护和运行(。另外,据我所知,Daffodil是目前唯一支持inputValueCalc和outputValueCalc的DFDL处理器,因此符合规范在这里并不是特别有价值。

2( 最新版的水仙花 (2.4.0( 包含专为此问题设计的 DFDL 扩展。水仙花维基上提供的一些文档。

这里的理论是,你可以定义一个简单的类型,它是对xs:string的限制作为xsd枚举;然后提供相应的二进制值作为DFDL注释:

<xs:simpleType name="uint8" dfdl:length="1">
<xs:restriction base="xs:unsignedInt"/>
</xs:simpleType>
<xs:simpleType name="SomeEnumType" dfdlx:repType="tns:uint8">
<xs:restriction base="xs:string">
<xs:enumeration value="ENUM_1" dfdlx:repValues="0" />
<xs:enumeration value="ENUM_2" dfdlx:repValues="1" />
<xs:enumeration value="ENUM_3" dfdlx:repValues="2" />
</xs:restriction>
</xs:simpleType>
<xs:element name="SomeEnum" type="tns:SomeEnumType" />

这里的好处是架构更易于维护,Daffodil 将使用直接哈希表查找来执行查找,而不是需要遍历 if-else 树。

最新更新