1
resposta

Acessar um dicionário aninhado

Olá, pessoal.

Estou com uma tabela em Excel de quantitativos de obra que estou transformando em DataFrame no Pandas. Essa tabela é organizada de forma hierárquica usando algumas colunas de referência.

Exemplo:

C 0 0 0 0 OBRAS CIVIS

C 5 0 0 0 INSTALAÇÕES PROVISÓRIAS DE OBRAS / INSTALAÇÕES

C 5 5 0 0 MOBILIZAÇÃO

C 5 5 5 0 MOBILIZAÇÃO DE PESSOAL E EQUIPAMENTOS

Observem que se uma linha possui uma coluna com valor 0, quer dizer que este é um item mãe de um item subsequente.

Preciso transformar esse dataframe em um XML, para que essa hierarquia fique organizada dentro dele.

Talvez o Pandas tenha algum recurso mais elaborado, mas inicialmente o que pensei foi em transformar o dataframe em um dicionário e a partir disso fazer iterações:

def dictify(frame):
    d = {}
    for row in frame.values:
        here = d
        for elem in row[:-2]:
            if elem not in here:
                here[elem] = {}
            here = here[elem]
        here[row[-2]] = row[-1]
    return d

A minha função que traduz o dicionário em XML é essa daqui:

def json2xml(json_obj, line_padding=""):
    result_list = list()

    json_obj_type = type(json_obj)

    if json_obj_type is list:
        for sub_elem in json_obj:
            result_list.append(json2xml(sub_elem, line_padding))

        return "\n".join(result_list)

    if json_obj_type is dict:

        for k, tag_name in enumerate(json_obj):
            sub_obj = json_obj[tag_name]
            result_list.append('%s<viewfolder name="%s" guid="">' % (line_padding, tag_name))
            result_list.append(json2xml(sub_obj, "\t" + line_padding))
            result_list.append("%s</viewfolder>" % line_padding)

        return "\n".join(result_list)

    #return '%s<name internal="LcRevitData_Element">%s' % (line_padding, json_obj) + '</name>'
    return ('%s<selectionset name="%s" guid="">' % (line_padding, json_obj)  + ''
            '\n\t%s<name internal="LcRevitData_Element">%s' % (line_padding, json_obj) + '</name>'
            '\n\t%s<findspec mode="all" disjoint="0"' % line_padding + ''
            '\n\t%s<conditions>' % line_padding + ''
            '\n\t%s<category>' % line_padding + ''
            '\n\t%s\t<name internal="LcRevitData_Element">%s</name>' % (line_padding, json_obj) + ''
            '\n\t%s</category>' % line_padding + ''
            '\n\t%s<property>' % line_padding + ''
            '\n\t%s\t<name internal="lcldrevit_parameter_7977469">.CWP</name>' % line_padding + ''
            '\n\t%s</property>' % line_padding + ''
            '\n\t%s<value>' % line_padding + ''
            '\n\t%s\t<data type="wstring">>>>>CODIFICAÇÃO CHEIA<<<<<</data>' % line_padding + ''
            '\n\t%s</value>' % line_padding + ''
            '\n\t%s</conditions>' % line_padding + ''
            '\n%s</selectionset>' % line_padding + '')

No entanto, estou tendo problemas pois no último return do código, eu precisaria da codificação CHEIA, ou seja, algo como C.5.5.5.5 por exemplo, por isso, preciso de todos os parentes dentro dessa árvore para conseguir.

Alguma ideia? Obrigado!

1 resposta

Oii Thomaz, como você está?

Estou aqui para te ajudar, porém, analisando o seu código, sem tê-lo completo e fazendo os testes, não consegui visualizar o problema. Você poderia compartilhar o seu projeto para que eu possa fazer os testes e te nortear melhor quanto a sua necessidade?

Também, se puder dar exemplos de como está sendo a saída com as tags xml e como seria a saída esperada.

Além disso, o que seria a saída cheia? Ela tem algum tipo de padrão? Como ela é montada? Por exemplo: a saída cheia será o número que estiver na quarta coluna.

Fico no aguardo para poder te ajudar :) A gente vai conversando.