免责声明,我是实现以下选项 2 的 Daffodil 开发人员。
我不相信 IBM DFDL 对这个问题有很好的解决方案。
Daffodil 提供两种解决方案:
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 树。