0

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

在此处输入图像描述

XML/Tree 输出预期如下

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

1 回答 1

1

像这样的解决方案是一种可能的解决方案,在 Daffodil 中进行了测试:

<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 是空字符串的一些事情会导致问题。经过反复试验,我发现如果您指定应将空值元素视为 nil,IBM DFDL(和 Apache Daffodil 也一样)可以接受。因此,将 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 类似的行为。

于 2021-05-17T12:59:49.007 回答