Рубрики
Без рубрики

Обработка данных XML

Обработка данных XML На протяжении десятилетий XML был доминирующим форматом много приложений, используемых … Теги с Python, начинающими, наукой данных.

В течение десятилетий XML был формат доминирования, многие приложения используются для связи друг с другом. В последние годы XML стал менее и менее популярным в качестве формата данных для полуструктурированных случаев данных. Сейчас в современном облачном родном, микросервис приложения JSON или YAML стали нормой. Однако это не изменяет тот факт, что большая часть систем, инструментов и бизнес-процесса все еще на месте. XML – это также формат Defacto «нейтральный» для преобразования конкретных типов файлов в отрасли. Как профессиональный аналитик, способный обрабатывать XML так же легко, как CSV, является обязательным.

В этом посте мы создадим сценарий обработки пакетных данных для типичной лабораторной отчетности. Сценарий, техник, Susian, в конце каждого дня анализирует результаты тестирования отделов. Лабораторное оборудование выводит результаты теста как XML. Susian требует, чтобы XML был преобразован в CSV, чтобы накормить отчет Excel, которую она была предоставлена.

Я буду использовать образец лабораторного измерения-набора данных, который я автоматически генерируется в предыдущем посте здесь.

Содержание

  • Обработка данных XML
    • Конвертировать XML в CSV
    • Шассинг XML: Корневой элемент
    • Sharsing XML: элементы первого уровня
    • Sharsing XML: подэлементы
    • XML Parser Class.
    • Пакетное исполнение
    • Сохранить преобразованный набор данных
    • TL; доктор

Конвертировать XML в CSV

Пример файла XML.



  
    Machine_10
    3c0c95f773bf426585a3a68642d2d41a
    Brett Kerr
    c/f/a/b
    Yes
    
      8.63
      0.39661
      3736
    
    
      -4.94
      0.964363
      3182
    
  

Целевая структура таблицы

да 87729203DFCE4E9DA7EFBBB985C83BD9. 47.81 1.878128 871 Machine_03. Стейси Симпсон D / A / F loc_1.
да 87729203DFCE4E9DA7EFBBB985C83BD9. -2.10 0.995672 4694 Machine_03. Стейси Симпсон D / A / F loc_2.
да 98910CAE86864C3697E6E7FCCFB8CC33. 2.50 0.236024 3034 Machine_03. Бритни Грей F / D / A loc_1.

Шассинг XML: Корневой элемент

Чтобы обработать анализ XML, мы будем использовать Импорт XML.etreee. Elementtree упаковка. Ключ к разбору XML является создание класса, представляющего один файл и методы, которые переводят каждый элемент. В примере файла первый элемент для изолята будет каждый Datafile для Детали коллекция:

import xml.etree.ElementTree as ET
import uuid
import pandas as pd
import glob
file_path = '/sample-data-set/auto-gen/xml/a8971cf83bd84fd1b366bfb312278021.xml'
with open(file_path) as f:
    tree = ET.parse(f)
    rootElem = tree.getroot()

    # Select each DataFile
    for data_file in rootElem.findall('DataFile'):
        print(data_file.get('id'))
>>> output:
d7ecf46df41f4355a23c42c4607266c7

Sharsing XML: элементы первого уровня

Затем извлеките информацию «заголовка» для каждого теста

file_path = '/sample-data-set/auto-gen/xml/a8971cf83bd84fd1b366bfb312278021.xml'
with open(file_path) as f:
    tree = ET.parse(f)
    rootElem = tree.getroot()
for data_file in rootElem.findall('DataFile'):
    m_id = data_file.find('machine_id').text
    test_id = data_file.find('test_id').text
    tech_id = data_file.find('technician').text
    test_routine = data_file.find('test_routine').text
    batched = data_file.find('batched').text

    header_ar = [m_id, test_id, tech_id, test_routine, batched]
    print(header_ar)
>>> output:
['Machine_03', '9e0f95807ed44a468271eb6d3ff85a44', 'Jennifer Johnson', 'd', 'N/A']

Sharsing XML: подэлементы

Наконец, извлечь данные измерений для loc_1 и loc_2

file_path = '/sample-data-set/auto-gen/xml/a8971cf83bd84fd1b366bfb312278021.xml'

def parse_measurement_location(dataFile, loc_name):
    res = []
    measurement_loc = dataFile.find(loc_name)
    measurement_loc_id = measurement_loc.tag
    x_m = measurement_loc.find('x_offset').text
    y_m = measurement_loc.find('y_offset').text
    z_m = measurement_loc.find('z_offset').text

    return [measurement_loc_id,x_m,y_m,z_m]

with open(file_path) as f:
    tree = ET.parse(f)
    rootElem = tree.getroot()
for data_file in rootElem.findall('DataFile'):
    file_ar = []
    m_id = data_file.find('machine_id').text
    test_id = data_file.find('test_id').text
    tech_id = data_file.find('technician').text
    test_routine = data_file.find('test_routine').text
    batched = data_file.find('batched').text

    header_ar = [m_id, test_id, tech_id, test_routine, batched]

    loc_ar = parse_measurement_location(data_file, 'loc_1')
    file_ar.append(header_ar + loc_ar)

    loc_ar = parse_measurement_location(data_file, 'loc_2')
    file_ar.append(header_ar + loc_ar)
    print(file_ar)


>>> output:
[['Machine_03', '9e0f95807ed44a468271eb6d3ff85a44', 'Jennifer Johnson', 'd', 'N/A', 'loc_1', '17.35', '1.3074', '752'], 

['Machine_03', '9e0f95807ed44a468271eb6d3ff85a44', 'Jennifer Johnson', 'd', 'N/A', 'loc_2', '2.68', '0.575979', '4483']]

XML Parser Class.

Затем мы помещаем логику преобразования в класс, который можно призвать для любого файла:

# Parsing class
class Xml_Parser:
    def __init__(self):
        self.ResultAr = []
        return
    def parse_datafiles(self,file_id,rootElem):
        res = []
        for data_file in rootElem.findall('DataFile'):
            file_ar = self.parse_file(data_file)
            res += file_ar
        return res
    def parse_file(self, data_file):

        file_ar = []
        m_id = data_file.find('machine_id').text
        test_id = data_file.find('test_id').text
        tech_id = data_file.find('technician').text
        test_routine = data_file.find('test_routine').text
        batched = data_file.find('batched').text

        header_ar = [m_id, test_id, tech_id, test_routine, batched]

        loc_ar = self.parse_measurement_location(data_file, 'loc_1')
        file_ar.append(header_ar + loc_ar)

        loc_ar = self.parse_measurement_location(data_file, 'loc_2')
        file_ar.append(header_ar + loc_ar)

        return file_ar
    def parse_measurement_location(self, dataFile, loc_name):
        res = []
        measurement_loc = dataFile.find(loc_name)
        measurement_loc_id = measurement_loc.tag
        x_m = measurement_loc.find('x_offset').text
        y_m = measurement_loc.find('y_offset').text
        z_m = measurement_loc.find('z_offset').text

        return [measurement_loc_id,x_m,y_m,z_m]

Пакетное исполнение

Чтобы сделать пакетное преобразование на набор файлов, нам понадобится:

  1. Проанализируйте данный файл, выполнив наш разборщик
  2. Найти все тестовые файлы
# Conversion executor function
def convert_xml_to_list(file_path):
    with open(file_path) as f:
        tree = ET.parse(f)
        root = tree.getroot()
        parser_obj = Xml_Parser()
        xml_list = parser_obj.parse_datafiles(f,root)
    return xml_list
# Batch executor
def batch_convert_xml_to_df(xml_dir, dataset_columns,file_limit=-1):
    i=0
    converted_dataset = []
    # Recursively convert each target file
    for filepath in glob.iglob(xml_dir, recursive=True):
        c_ds = convert_xml_to_list(filepath)
        converted_dataset+=c_ds

        i+=1
        if (i >= file_limit) and (file_limit>=0): break

    df = pd.DataFrame(converted_dataset, columns = dataset_columns) 
    return df

Сохранить преобразованный набор данных

Последний шаг – принести все кусочки вместе преобразовывать и сохранить папку XML-файлов в один CSV.

measurement_file_path = '/sample-data-set/auto-gen/xml/*.xml'
measurement_columns = ['machine_id','test_id','technician','test_routine','batched','measurement_location_id','x_offset','y_offset','z_offset']
file_process_limit = 20 # Set to -1 for unlimited

converted_file_dir = '/sample-data-set/auto-gen/converted'

lab_measurement_df = batch_convert_xml_to_df(measurement_file_path, measurement_columns, file_process_limit)

# Save dataset to csv using unique name
destPath = '/'.join([converted_file_dir,str(uuid.uuid4().hex)])
destPath = '.'.join([destPath,'csv'])

lab_measurement_df.to_csv(destPath, index = False, header=True)

lab_measurement_df.head()
да 87729203DFCE4E9DA7EFBBB985C83BD9. 47.81 1.878128 871 0 Machine_03. Стейси Симпсон D / A / F loc_1.
да 87729203DFCE4E9DA7EFBBB985C83BD9. -2.10 0.995672 4694 1 Machine_03. Стейси Симпсон D / A / F loc_2.
да 98910CAE86864C3697E6E7FCCFB8CC33. 2.50 0.236024 3034 2 Machine_03. Бритни Грей F / D / A loc_1.
да 98910CAE86864C3697E6E7FCCFB8CC33. -13.38 0.795762 4337 3 Machine_03. Бритни Грей F / D / A loc_2.
Нет f505ffc52ad34b56a9f7f95451a813c3. 44.20 1.982816 830 4 Machine_03. Джон Король C / F / E loc_1.

TL; доктор

Полный скрипт здесь

Оригинал: “https://dev.to/darrylbrysondev0/xml-batch-data-processing-4fem”