首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >枚举二进制数据的DFDL解码

枚举二进制数据的DFDL解码
EN

Stack Overflow用户
提问于 2019-09-30 20:58:17
回答 1查看 290关注 0票数 1

我目前正在为系统中使用的遗留(自定义)二进制文件格式开发一种DFDL模式,以将其转换为XML或JSON。

我得到了一些二进制数据,即枚举值,即C-struct数据类型如下所示(并存储为一个字节):

代码语言:javascript
复制
typedef enum _SomeEnum
{
  ENUM_1 = 0x00,
  ENUM_2 = 0x01,
  ENUM_3 = 0x02
} SomeEnum;

使用下面的DFDL模式代码(包括检查),我可以将枚举解码为一个数值:

代码语言:javascript
复制
<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:

代码语言:javascript
复制
<SomeEnum>1</SomeEnum>

我想要的是能够将解码的枚举值转换为字符串,这样XML结果看起来就像这样:

代码语言:javascript
复制
<SomeEnum>ENUM_1</SomeEnum>

但我不确定如何使用DFDL来实现这一点。

我使用Daffodil作为我的DFDL解析器/处理器(尽管我怀疑IBM-integration-bus DFDL解析器也能做到这一点)

EN

回答 1

Stack Overflow用户

发布于 2019-09-30 22:44:48

免责声明,我是Daffodil开发人员,他实现了下面的选项2。

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

Daffodil提供了两种解决方案:

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

代码语言:javascript
复制
<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上提供了一些文档。

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

代码语言:javascript
复制
<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树。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58168427

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档