Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 枚举二进制数据的DFDL解码_Java_Xml_Ibm Integration Bus_Dfdl - Fatal编程技术网

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

Java 枚举二进制数据的DFDL解码,java,xml,ibm-integration-bus,dfdl,Java,Xml,Ibm Integration Bus,Dfdl,我目前正在为系统中用于转换为XML或JSON的遗留(自定义)二进制文件格式开发DFDL模式 我有一些二进制数据是枚举值,即C-struct数据类型如下(并存储为字节): 使用此DFDL模式代码(包括检查),我可以将枚举解码为数值: 免责声明,我是实现下面选项2的水仙花开发人员 我不相信IBMDFDL能很好地解决这个问题 水仙花提供两种解决方案: 1) 使用inputValueCalc/outputValueCalc。这里的理论是,首先将枚举解析为整数(可能在隐藏组中),然后使用DFDL表达式计算

我目前正在为系统中用于转换为XML或JSON的遗留(自定义)二进制文件格式开发DFDL模式

我有一些二进制数据是枚举值,即C-struct数据类型如下(并存储为字节):

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


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

我不相信IBMDFDL能很好地解决这个问题

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

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扩展。网站上提供了一些文档

这里的理论是,您可以将一个简单类型定义为xsd枚举,该类型是对xs:string的限制;然后提供相应的二进制值作为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树。

谢谢,这正是我需要的。我昨天遇到了inputValueCalc,但我意识到它对于大型枚举来说非常不方便。第二种选择要优雅得多。我唯一的问题是Daffodil解析器抛出了以下内容(我认为这与字符串的长度有关):[error]模式定义错误:当lengthind='implicit'时,必须同时指定minLength和maxLength方面。添加xs:minLength和xs:maxLength,解析器会抱怨它们需要是相同的值。如果将它们设置为相同的值,解析器就会崩溃。不确定这些应该是什么,我找到了这个。它使用inputTypeCalcString inputValueCalc函数,但这只是抛出了一个错误,即inputTypeCalcString是一个不受支持的函数;并且提供给dfdlx:repType的类型不应该是内置的xsd类型。
<SomeEnum>1</SomeEnum>
<SomeEnum>ENUM_1</SomeEnum>
<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>
<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" />