我目前正在研究一种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>


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

<SomeEnum>1</SomeEnum>


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

<SomeEnum>ENUM_1</SomeEnum>


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

我使用Daffodil作为DFDL解析器/处理器(尽管我怀疑IBM集成总线DFDL解析器也可以做到这一点)

最佳答案

免责声明,我是实施以下选项2的Daffodil开发人员。

我认为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)最新版本的Daffodil(2.4.0)包含一个专门为此问题设计的DFDL扩展。 Daffodil wiki上的一些文档。

这里的理论是,您可以定义一个简单类型,该类型对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树。

07-28 03:30