微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

用于解析分隔文本消息的 DFDL 架构

如何解决用于解析分隔文本消息的 DFDL 架构

需要 dfdl 的小帮助。我需要将下面的消息解析为 XML/树结构之类的东西。元素不是固定的和动态的。有时会出现一些其他元素。

enter image description here

XML/Tree 输出预期如下

<root>
<CLIENT_ID>DESKTOPCLIENT</CLIENT_ID>
<LOCALE>en-US</LOCALE>
<ENCODE/>
</root>

解决方法

这样的事情是一个可能的解决方案,在水仙花中进行了测试:

<xs:schema
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/">

  <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd" />

  <xs:annotation>
    <xs:appinfo source="http://www.ogf.org/dfdl/">
      <dfdl:format
        ref="GeneralFormat"
        lengthKind="delimited"
      />
    </xs:appinfo>
  </xs:annotation>

  <xs:element name="root" dfdl:initiator="%ESC;" dfdl:terminator="%SUB;">
    <xs:complexType>
      <xs:sequence dfdl:separator="%CAN;" dfdl:separatorPosition="prefix" dfdl:sequenceKind="unordered">
        <xs:element name="CLIENT_ID" type="xs:string" dfdl:initiator="CLIENT_ID%NAK;" />
        <xs:element name="LOCALED" type="xs:string" dfdl:initiator="LOCALE%NAK;" />
        <xs:element name="ENCODE" type="xs:string" dfdl:initiator="ENCODE%NAK;" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>

</xs:schema>

请注意,这假定单个元素的名称是固定的,并且它们都存在,尽管顺序无关紧要。如果您知道固定名称,但它们可能存在也可能不存在,您可以将 minOccurs="0" 添加到无序序列中的元素。

但是,DFDL 不允许动态元素名称,因此如果您不知道名称,则需要稍微不同的架构。相反,您需要将数据描述为无限数量的名称/值对,其中名称和值由 %NAK; 分隔,例如:

  <xs:element name="root" dfdl:initiator="%ESC;" dfdl:terminator="%SUB;">
    <xs:complexType>
      <xs:sequence dfdl:separator="%CAN;" dfdl:separatorPosition="prefix">
        <xs:element name="element" maxOccurs="unbounded">
          <xs:complexType>
            <xs:sequence dfdl:separator="%NAK;" dfdl:separatorPosition="infix">
              <xs:element name="name" type="xs:string" />
              <xs:element name="value" type="xs:string" />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

这会产生一个看起来像这样的信息集:

<root>
  <element>
    <name>CLIENT_ID</name>
    <value>DESKTOPCLIENT</value>
  </element>
  <element>
    <name>LOCALE</name>
    <value>en-US</value>
  </element>
  <element>
    <name>ENCODE</name>
    <value></value>
  </element>
</root>

如果您需要 XML 标记来匹配问题中的名称字段,则您需要转换信息集。 XSLT 可以轻松完成这种转换。

编辑:似乎存在 IBM DFDL 不喜欢上述解决方案的问题。我不知道为什么,但它适用于 Apache Daffodil。关于 value 是空字符串的一些事情会导致问题。经过反复试验,我发现 IBM DFDL(和 Apache Daffodil 也是如此)可以接受,如果您指定空值元素应视为 nil。因此,将 value 元素更改为此有效:

<xs:element name="value" type="xs:string" nillable="true"
  dfdl:nilKind="literalValue" dfdl:nilValue="%ES;"
  dfdl:useNilForDefault="no"/>

在这种情况下,信息集最终会是这样的:

<element>
  <name>ENCODE</name>
  <value xsi:nil="true"></value>
</element>

Edit2:nillable 属性是必需的,否则 IBM DFDL 会将空字符串值视为不存在而不是具有空值。缺席会导致错误。较新版本的 DFDL 规范添加了一个新属性 emptyElementParsePolicy,它允许您控制是将空字符串视为不存在还是仅将其视为空字符串。 Daffodil 将此属性实现为扩展,但默认为将其视为空行为。 IBM DFDL 将视为缺席行为。将此属性设置为不存在时,Daffodil 具有与 IBM DFDL 类似的行为。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。