@kripton3000
Бекенд- и немного фронтенд-разработчик

Как в Python реализовать рекурсивное построение XML по объекту?

На входе в программу имеется объект (словарь) - дерево, такого вида:

object_tree = 
{'attribs': [],
 'childs': [{'attribs': [],
             'childs': [{'attribs': [],
                         'childs': [{'attribs': [],
                                     'childs': [],
                                     'is_text': True,
                                     'level': 4,
                                     'name': 'quantity',
                                     'parrent': 'inventory',
                                     'skip_if_not': True,
                                     'text_type': 'in_line',
                                     'text_value': 'qty'}],
                         'is_text': False,
                         'level': 3,
                         'name': 'inventory',
                         'parrent': 'product',
                         'skip_if_not': False,
                         'text_type': False,
                         'text_value': False},
                        {'attribs': [],
                         'childs': [],
                         'is_text': True,
                         'level': 2,
                         'name': 'SKU',
                         'parrent': 'product',
                         'skip_if_not': True,
                         'text_type': 'in_line',
                         'text_value': 'customer_sku'}],
             'is_text': False,
             'level': 1,
             'name': 'product',
             'parrent': 'MAIN',
             'skip_if_not': False,
             'text_type': False,
             'text_value': False}],
 'is_text': False,
 'level': 0,
 'name': 'MAIN',
 'parrent': False,
 'skip_if_not': False,
 'text_type': False,
 'text_value': False}


И список словарей вида:

lines = [
    {
        "param1": None,
        "param2": "12423",
        "param3": 243,
    },
    {
        "param1": "rttui",
        "param2": "468790",
        "param3": 8978,
    },
    {
        "param1": "fhjkhjk",
        "param2": "t568679",
        "param3": 235645,
    },
]


Нужно на выходе получить XML, сформированный по этим данным.

Код:

from lxml.etree import tostring, Element, SubElement

def create_childs(parrent, obj_node, line):
    _cur_element = Element(obj_node['name'])
    if(bool(obj_node['is_text'])):
        if(obj_node['text_type'] == 'static'):
            _cur_element.text = obj_node['text_value']
            parrent.append(_cur_element)
            return parrent
        else:
            if(line.get(obj_node['text_value'], False)):
                _cur_element.text = line[obj_node['text_value']]
                parrent.append(_cur_element)
                return parrent
            else:
                if(bool(obj_node['skip_if_not'])):
                    return False
                else:
                    parrent.append(_cur_element)
                    return parrent
    if(len(obj_node['childs']) > 0):
        for child in obj_node['childs']:
            response = create_childs(_cur_element, child, line)
            if((response is not None) and (response is not False)):
                _child = response
                _cur_element.append(_child)
        parrent.append(_cur_element)
        return parrent


start = Element(object_tree['name'])
for line in lines:
    start = create_childs(start, object_tree, line)

print(tostring(start, pretty_print=True))


Получаю XML такого вида:

<MAIN>
  <MAIN>
    <product>
      <inventory>
        <quantity>12423</quantity>
      </inventory>
    </product>
  </MAIN>
  <MAIN>
    <product>
      <inventory>
        <quantity>468790</quantity>
      </inventory>
      <SKU>rttui</SKU>
    </product>
  </MAIN>
  <MAIN>
    <product>
      <inventory>
        <quantity>t568679</quantity>
      </inventory>
      <SKU>fhjkhjk</SKU>
    </product>
  </MAIN>
</MAIN>


Как видно в первой секции inventory отсутствует SKU, не могу реализовать такой алгоритм, который бы при пустом SKU в line вообще бы не вставлял полностью секцию:

<MAIN>
    <product>
      <inventory>
        <quantity>12423</quantity>
      </inventory>
    </product>
  </MAIN>
  • Вопрос задан
  • 3030 просмотров
Пригласить эксперта
Ответы на вопрос 1
Fesor
@Fesor
Full-stack developer (Symfony, Angular)
Ну либо извращаться с выводом вашей рекурсивной функции, либо вообще отказаться от рекурсии.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы
23 нояб. 2024, в 01:31
1000 руб./за проект
23 нояб. 2024, в 00:16
2000 руб./за проект
22 нояб. 2024, в 23:55
3000 руб./за проект