Создание csv из XML с повторяющимися тегами - PullRequest
0 голосов
/ 10 июля 2020

Я пытаюсь нормализовать файл xml, у которого есть родительский тег с повторяющимися дочерними тегами. См. Образец данных ниже:

<GeneralQuestions>
    <HeaderText>Pain Management Assessment</HeaderText>
    <QuestionText>Pain assessment</QuestionText>
    <QuestionAnswer>Yes</QuestionAnswer>
    <HeaderText>Activities of Daily Living</HeaderText>
    <QuestionText>Patient walks</QuestionText>
    <QuestionAnswer>With Some Help</QuestionAnswer>
    <Score>1</Score>
    <HeaderText>Pain Management Assessment</HeaderText>
    <QuestionText>Patient consents to having Pain Management Assessment screening completed.</QuestionText>
    <QuestionAnswer>Patient accepts</QuestionAnswer>
    <HeaderText>Activities of Daily Living</HeaderText>
    <QuestionText>Patient gets dressed</QuestionText>
    <QuestionAnswer>With Some Help</QuestionAnswer>
    <Score>1</Score>
</GeneralQuestions>

Вы заметите, что дочерние теги в «GeneralQuestions» повторяются, а дочерний тег «Score» является необязательным. Я пытаюсь преобразовать его в нормализованную форму, в которой каждый набор дочерних тегов формирует строку, как показано ниже:

  1. HeaderText, QuestionText, QuestionAnswer, Score
  2. HeaderText, QuestionText , QuestionAnswer, Score
  3. HeaderText, QuestionText, QuestionAnswer, Score

Если «Оценка» отсутствует, мне нужно нулевое значение. Я использую python 3.7 и xml .etree.ElementTree.iterparse для анализа данных. Пожалуйста, дайте мне знать, как я могу нормализовать данные.

Ответы [ 2 ]

0 голосов
/ 14 июля 2020

Я создал контекст из файла XML:

xmlIter=ET.iterparse('C:\\Users\\ANAND_RA\\Documents\\Project\\XXXXXXX_MA_05042020_0.xml', events=('start','end'))
context=iter(xmlIter)

Затем я использовал a for l oop для анализа каждого тега:

for eachEvent, eachElement in context:

Последний шаг (наиболее важный) - обработать тег «GeneralQuestions» для l oop:

if eachElement.tag=='GeneralQuestions' and eachEvent=='start':
        GQstart=True
        GQcount=0
        GQlist=[]
        GQDataList=[]
    if eachElement.tag=='HeaderText' and GQstart and eachEvent=='start':
        if GQcount!=0:
            if len(GQlist)<6:
                GQlist.extend([None,1,today,today])
            else:
                GQlist.extend([1,today,today])
            GQDataList.append(tuple(GQlist))
        GQcount+=1
        GQlist=[]
        GQlist.extend([nextDLMemberSK,GQcount,eachElement.text])
    if eachElement.tag=='QuestionText' and GQstart and eachEvent=='start':
        GQlist.append(eachElement.text)
    if eachElement.tag=='QuestionAnswer' and GQstart and eachEvent=='start':
        GQlist.append(eachElement.text)
    if eachElement.tag=='Score' and GQstart and eachEvent=='start':
        GQlist.append(eachElement.text)
    if eachElement.tag=='GeneralQuestions' and eachEvent=='end' and GQcount!=0:
        if len(GQlist)==5:
            GQlist.extend([None,1,today,today])
        else:
            GQlist.extend([1,today,today])
        GQDataList.append(tuple(GQlist))
    if eachElement.tag=='GeneralQuestions' and eachEvent=='end' and len(GQDataList)>0:
#         print(GQDataList)
        cur1.executemany(SQL_INS_INOV_GENERALQ,GQDataList)

Обработка XML сильно отличается от обработки json файла. В json проверка данных более гибкая. Однако в данных xml вы должны проверить теги в том виде, в котором они представлены для l oop.

0 голосов
/ 10 июля 2020

Здесь неполный ответ, который поможет вам с помощью numpy пронумеровать теги. Я принял ту же структуру. Скажем, у нас есть

XML = """<GeneralQuestions>
    <HeaderText>Pain Management Assessment</HeaderText>
    <QuestionText>Pain assessment</QuestionText>
    <QuestionAnswer>Yes</QuestionAnswer>
    <HeaderText>Activities of Daily Living</HeaderText>
    <QuestionText>Patient walks</QuestionText>
    <QuestionAnswer>With Some Help</QuestionAnswer>
    <Score>1</Score>
    <HeaderText>Pain Management Assessment</HeaderText>
    <QuestionText>Patient consents to having Pain Management Assessment screening completed.</QuestionText>
    <QuestionAnswer>Patient accepts</QuestionAnswer>
    <HeaderText>Activities of Daily Living</HeaderText>
    <QuestionText>Patient gets dressed</QuestionText>
    <QuestionAnswer>With Some Help</QuestionAnswer>
    <Score>1</Score>
</GeneralQuestions>"""

И мы создаем дерево с

import xml.etree.ElementTree as ET
tree = ET.fromstring(XML)

Чем с помощью numpy мы можем создать индекс с

import numpy as np
index_of_score = np.cumsum( [ e.tag == 'HeaderText' for e in tree.getchildren() ] )

Теперь с с помощью index_of_score вы можете создать словарь с индексированными тегами и возможным значением

{ "{}_{}".format(a.tag,i) : a.text for i,a in zip(index_of_score, tree.getchildren() ) }

, которое даст вам

{'HeaderText_1': 'Pain Management Assessment',
 'QuestionText_1': 'Pain assessment',
 'QuestionAnswer_1': 'Yes',
 'HeaderText_2': 'Activities of Daily Living',
 'QuestionText_2': 'Patient walks',
 'QuestionAnswer_2': 'With Some Help',
 'Score_2': '1',
 'HeaderText_3': 'Pain Management Assessment',
 'QuestionText_3': 'Patient consents to having Pain Management Assessment screening completed.',
 'QuestionAnswer_3': 'Patient accepts',
 'HeaderText_4': 'Activities of Daily Living',
 'QuestionText_4': 'Patient gets dressed',
 'QuestionAnswer_4': 'With Some Help',
 'Score_4': '1'}

В зависимости от желаемого результата вы можете выбрать ценности, которые вам нужны. Скажем, в приведенном выше словаре dict_output, python есть хороший dict_output.get("Score_1", None), который даст вам либо значение, либо, в данном случае, None, которое может помочь вам в обработке данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...