Выход из цикла в DFDL - PullRequest
       37

Выход из цикла в DFDL

0 голосов
/ 23 октября 2018

Я пытаюсь преобразовать файл FLAT в XML, используя DFDL.Он имеет следующий формат: каждый элемент по 5 байт. Все находятся в одной строке, но я разделяю их, чтобы избежать путаницы.Я буду обращаться к элементам по первой букве в них.

0AAAA  
81AAA  
eeeee  
qqqqq    
82BBB    
rrrrr  
sssss  
9QQQQ  

Теперь 0 и 9 - бабушка и дедушка, нам не о чем беспокоиться.8 является родительским, а второй байт 81AAA (то есть 1) будет определять формат его дочерних элементов.Может быть много 8 и много детей от 8 родителей (но все они будут иметь одинаковый формат).
Я попробовал одну схему, но как только она переходит в дочерние (eeeee), она не выходит из нее, и каждая записьпечатается только в детском формате.

1 Ответ

0 голосов
/ 23 октября 2018

Ниже приведена схема, которая, как мне кажется, описывает ваши данные, протестированные на Daffodil 2.2.0:

<xs:schema
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  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" />
    </xs:appinfo>
  </xs:annotation>

  <xs:element name="Root">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="GrandParent" maxOccurs="unbounded">
          <xs:complexType>
            <xs:choice dfdl:initiatedContent="yes">
              <xs:element name="Zero" dfdl:initiator="0">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="Value" type="xs:string" dfdl:length="4" dfdl:lengthKind="explicit" />
                    <xs:element ref="Eight" minOccurs="0" maxOccurs="unbounded" />
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
              <xs:element name="Nine" dfdl:initiator="9">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="Value" type="xs:string" dfdl:length="4" dfdl:lengthKind="explicit" />
                    <xs:element ref="Eight" minOccurs="0" maxOccurs="unbounded" />
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:choice>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name="Eight" dfdl:initiator="8">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="ChildrenFormat" type="xs:string" dfdl:length="1" dfdl:lengthKind="explicit" />
        <xs:element name="Value" type="xs:string" dfdl:length="3" dfdl:lengthKind="explicit" />
        <xs:choice dfdl:choiceDispatchKey="{ ./ChildrenFormat }">
          <xs:element ref="One" maxOccurs="unbounded" dfdl:choiceBranchKey="1" />
          <xs:element ref="Two" maxOccurs="unbounded" dfdl:choiceBranchKey="2" />
        </xs:choice>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name="One" type="xs:string" dfdl:length="5" dfdl:lengthKind="explicit">
    <xs:annotation>
      <xs:appinfo source="http://www.ogf.org/dfdl/">
        <dfdl:discriminator test="{ fn:not(fn:starts-with(., '8') or fn:starts-with(., '9')) }" />
      </xs:appinfo>
    </xs:annotation>
  </xs:element>

  <xs:element name="Two" type="xs:string" dfdl:length="5" dfdl:lengthKind="explicit">
    <xs:annotation>
      <xs:appinfo source="http://www.ogf.org/dfdl/">
        <dfdl:discriminator test="{ fn:not(fn:starts-with(., '8') or fn:starts-with(., '9')) }" />
      </xs:appinfo>
    </xs:annotation>
  </xs:element>

</xs:schema>

Описание того, как это работает:

  • Кореньdata - это неограниченное количество элементов GrandParent
  • Каждый элемент GrandParent содержит либо ноль, либо девятку, в зависимости от инициатора.Инициатор потребляет первый из 5 байтов данных прародителя
  • Элементы Zero / Nine содержат значение, которое потребляет оставшиеся 4 байта данных родительского элемента
  • После значения ноль или болееВосемь элементов
  • Каждый элемент Eight имеет инициатор "8", который потребляет первый из 5 байтов
  • Каждый элемент Eight имеет формат ChildrenFormat, который потребляет второй из 5 байтов
  • Каждый восьмой элемент имеет значение, которое занимает последние 3 из 5 байтов
  • Каждый восьмой элемент имеет неограниченное число либо всех одного, либо всех двух элементов
  • choiceDispatchKey / Branch используется для определения того,чтобы проанализировать все один или все два элемента, отправка из элемента ChildrenFormat
  • каждого одного или двух элементов занимает 5 байтов
  • , чтобы определить, когда заканчивается неограниченное число элементов одного или двух,дискриминатор размещается на элементах One / Two.Этот дискриминатор не работает, если данные, проанализированные как один / два, не начинаются с «8» или «9».
  • Кроме того, все поля для простоты обрабатываются как строки

При этом данные вашего примера анализируются в информационный набор, например:

<Root>
  <GrandParent>
    <Zero>
      <Value>AAAA</Value>
      <Eight>
        <ChildrenFormat>1</ChildrenFormat>
        <Value>AAA</Value>
        <One>eeeee</One>
        <One>qqqqq</One>
      </Eight>
      <Eight>
        <ChildrenFormat>2</ChildrenFormat>
        <Value>BBB</Value>
        <Two>rrrrr</Two>
        <Two>sssss</Two>
      </Eight>
    </Zero>
  </GrandParent>
  <GrandParent>
    <Nine>
      <Value>QQQQ</Value>
    </Nine>
  </GrandParent>
</Root>
...