generateDS прекращает обработку дочерних элементов - PullRequest
0 голосов
/ 06 мая 2019

У меня есть XML-схема, которая описывает структуру электронного счета. Я использовал схему с generateDS для создания синтаксического анализатора для этого формата. При синтаксическом анализе счета, кажется, работает нормально, но в разделе, где есть контент любого типа, он останавливает обработку дочерних элементов, где появляются эти элементы.

Часть схемы, которая описывает любой элемент:

<!-- Elements to describe the invoice extensions -->
    <xs:complexType name="ExtensionRecord">
        <xs:sequence>
            <xs:element name="InformationName" type="NormalTextType" minOccurs="0"/>
            <xs:element name="InformationContent" type="LongTextType"/>
            <xs:element name="CustomContent" minOccurs="0">
                <xs:complexType>
                    <xs:sequence>
                        <xs:any processContents="skip"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
        <xs:attribute name="extensionId" type="ShortTextType" use="optional"/>
    </xs:complexType>

Соответствующая часть моей реализации, которая использует синтаксический анализатор:

E_Invoice = einvoice111.parseString(xmlString, silence=True)

for ai in E_Invoice.Invoice.AdditionalInformation:
    print(dir(ai) )
    print(dir(ai.CustomContent))
    print(ai.CustomContent.export(sys.stdout, 0, name_='CustomContent'))

Часть XML полезной нагрузки:

    <AdditionalInformation extensionId="invoicePDFFormat">
      <InformationContent/>
      <CustomContent>
        <any>
          <Content>JVBERi0xLjQ........
                    <BASE64 coded binary>
        .....</Content>

и вывод этого кода:

['CustomContent', 'InformationContent', 'InformationName', 'Tag_strip_pattern_', '_FixedOffsetTZ', '__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'build', 'buildAttributes', 'buildChildren', 'convert_unicode', 'export', 'exportAttributes', 'exportChildren', 'extensionId', 'factory', 'gds_build_any', 'gds_encode', 'gds_format_base64', 'gds_format_boolean', 'gds_format_boolean_list', 'gds_format_date', 'gds_format_datetime', 'gds_format_double', 'gds_format_double_list', 'gds_format_float', 'gds_format_float_list', 'gds_format_integer', 'gds_format_integer_list', 'gds_format_string', 'gds_format_time', 'gds_parse_date', 'gds_parse_datetime', 'gds_parse_time', 'gds_reverse_node_mapping', 'gds_str_lower', 'gds_validate_base64', 'gds_validate_boolean', 'gds_validate_boolean_list', 'gds_validate_date', 'gds_validate_datetime', 'gds_validate_double', 'gds_validate_double_list', 'gds_validate_float', 'gds_validate_float_list', 'gds_validate_integer', 'gds_validate_integer_list', 'gds_validate_simple_patterns', 'gds_validate_string', 'gds_validate_time', 'get_CustomContent', 'get_InformationContent', 'get_InformationName', 'get_class_obj_', 'get_extensionId', 'get_path_', 'get_path_list_', 'hasContent_', 'original_tagname_', 'set_CustomContent', 'set_InformationContent', 'set_InformationName', 'set_extensionId', 'subclass', 'superclass', 'tzoff_pattern', 'validate_LongTextType', 'validate_NormalTextType', 'validate_ShortTextType']
['Tag_strip_pattern_', '_FixedOffsetTZ', '__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'anytypeobjs_', 'build', 'buildAttributes', 'buildChildren', 'convert_unicode', 'export', 'exportAttributes', 'exportChildren', 'factory', 'gds_build_any', 'gds_encode', 'gds_format_base64', 'gds_format_boolean', 'gds_format_boolean_list', 'gds_format_date', 'gds_format_datetime', 'gds_format_double', 'gds_format_double_list', 'gds_format_float', 'gds_format_float_list', 'gds_format_integer', 'gds_format_integer_list', 'gds_format_string', 'gds_format_time', 'gds_parse_date', 'gds_parse_datetime', 'gds_parse_time', 'gds_reverse_node_mapping', 'gds_str_lower', 'gds_validate_base64', 'gds_validate_boolean', 'gds_validate_boolean_list', 'gds_validate_date', 'gds_validate_datetime', 'gds_validate_double', 'gds_validate_double_list', 'gds_validate_float', 'gds_validate_float_list', 'gds_validate_integer', 'gds_validate_integer_list', 'gds_validate_simple_patterns', 'gds_validate_string', 'gds_validate_time', 'get_anytypeobjs_', 'get_class_obj_', 'get_path_', 'get_path_list_', 'hasContent_', 'original_tagname_', 'set_anytypeobjs_', 'subclass', 'superclass', 'tzoff_pattern']
<CustomContent/>

CustomContent имеет omittag, показывающий, что структура объекта заканчивается там. Я также попытался export() весь документ, и у него такая же ситуация.

Так что это часть:

    <xs:complexType>
      <xs:sequence>
        <xs:any processContents="skip"/>
      </xs:sequence>
    </xs:complexType>

, который не отображается в дереве объектов Python.

Когда я смотрю на сгенерированную библиотеку, которая соответствует схеме, соответствующая часть класса CustomContent:

    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
        obj_ = self.gds_build_any(child_, 'CustomContentType')
        if obj_ is not None:
            self.set_anytypeobjs_(obj_)

Он использует метод gds_build_any() вместо создания нового экземпляра класса, который он сгенерировал бы из схемы (которого тоже не существует).

При использовании Suds я могу получить доступ к любому элементу и его содержимому, но в других местах он ломается.

Есть ли способ настроить generateDS так, чтобы он:

  • создать классы для всех элементов схемы?
  • использовать эти классы для всего документа?

Ответы [ 2 ]

0 голосов
/ 10 мая 2019

Хорошо, попробовал все виды подходов и предложил изменения, чтобы я мог прочитать любой контент (не уверен, знал ли я, что я делаю):

$ hg diff generateDS.py | wc -l
78

Единственная проблема, которая есть в моем XMLBase64 закодированный текст внутри.Это выглядит так:

    <AdditionalInformation extensionId="invoicePDFFormat">
      <InformationContent/>
      <CustomContent>
        <any>
          <Content>JVBERi0xLjQNCiXi48/TDQoxIDAgb2JqDQo8PC9UeXBlIC9Gb250IC9TdWJ0eXBlIC9UeXBlMQ0K
L0VuY29kaW5nIC9XaW5BbnNpRW5jb2RpbmcgL0Jhc2VGb250IC9Db3VyaWVyID4+DQplbmRvYmoN
CjIgMCBvYmoNCjw8IC9GaWx0ZXIgL0ZsYXRlRGVjb2RlIC9MZW5ndGggOTIgPj4NCnN0cmVhbQ0K
eJwz0DNVMIDionQFpxAuAwVDBV1DBQMFUwUTAwOFkFwu/WAPUyAvJA0oF1IMlAkpAhHJIKKcS8NV

, но после GDS-обработки это выглядит так:

          JVBERi0xLjQNCiXi48/TDQoxIDAgb2JqDQo8PC9UeXBlIC9Gb250IC9TdWJ0eXBlIC9UeXBlMQ0K

L0VuY29kaW5nIC9XaW5BbnNpRW5jb2RpbmcgL0Jhc2VGb250IC9Db3VyaWVyID4+DQplbmRvYmoN

CjIgMCBvYmoNCjw8IC9GaWx0ZXIgL0ZsYXRlRGVjb2RlIC9MZW5ndGggOTIgPj4NCnN0cmVhbQ0K

Я получаю текстовое содержимое внутри элемента с помощью:

self.any = ''.join(node.itertext())

и это не имеет значения, даже если бы я использовал только node.text, внутри него есть пустые строки.Это все еще неразгаданная тайна.

0 голосов
/ 09 мая 2019

Ну, по крайней мере кажется, что SAX-обработчик generateDS.py XschemaHandler в строке 1652 тестирует:

    if name == AnyType:
        element = XschemaElement(attrs)
        element.type = AnyTypeIdentifier
        self.stack.append(element)

и это соответствует тегу (AnyType содержит «xs: any»). Таким образом, GDS знает, что любой тег представляет собой специальную XML-грамматику, такую ​​как 'sequence', 'simpleType', 'complexType' и т. Д.

Это, вероятно, причина, по которой он не пытается создать класс для него и сопоставить его с 'any'.

Я немного его изменил:

    elif name == AnyType:
        print('opening AnyType')
        element = XschemaElement(attrs)
        element.name = 'any'
        #element.type = 'NormalTextType'
        element.type = 'StringType'
        self.inAnyType = 1
        self.stack.append(element)

и сделал аналогично закрывающему тегу саксофона, и добавил его к части обработки контента:

    def characters(self, chrs):
        if self.inDocumentationType:
            # If there is an annotation/documentation element, save it.
            if len(self.stack) > 1 and len(chrs) > 0:
                self.stack[-1].documentation += chrs
        elif self.inAnyType:
            if len(self.stack) > 1 and len(chrs) > 0:
                self.stack[-1].any += chrs
        elif self.inElement:
            pass

Теперь я получаю вывод как:

    <CustomContent>
        <any>

              </any>
    </CustomContent>

Близко, но без сигары.

...