Преобразование XML данных в Pandas - PullRequest
0 голосов
/ 29 мая 2020

Я хочу извлечь данные из XML и преобразовать их в Pandas Data Frame

Сначала я попытался импортировать с помощью Element Tree xml и просто распечатать некоторые столбцы с этим кодом , не повезло

Итак, пока мне удалось извлечь некоторые данные с помощью этого кода


import xml.etree.cElementTree as et
import pandas as pd
def getvalueofnode(node):
    """ return node text or None """
    return node.text if node is not None else None
def main():
    """ main """
    parsed_xml = et.parse("RTS_XTV100006361.xml")
    dfcols = ['start', 'stop', 'channel', 'type', 'title', 'category']
    df_xml = pd.DataFrame(columns=dfcols)
    for node in parsed_xml.getroot():
        start = node.attrib.get('start')
        stop = node.attrib.get('stop')
        channel = node.attrib.get('channel')
        type = node.attrib.get('type')
        title = node.find('title')
        category = node.find('category')
        df_xml = df_xml.append(
            pd.Series([start, stop, channel, type, getvalueofnode(category), getvalueofnode(title)], index=dfcols),
            ignore_index=True)
    print (df_xml)'

Но заголовок и категория все еще пусты

Это пример XML:

    <?xml version="1.0" encoding="utf-8"?>
<tv xmlns="http://www.xmltv.org/xmltv" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <programme ID="58135" start="20200528000000 +0200" stop="20200528013000 +0200" channel="XTV100006361" recordable="Y" npvrenable="Y" cpvrenable="N" type="program" deleted="false">
    <blackoutInfo>
      <isBlackout>1</isBlackout>
      <groupIDs>2</groupIDs>
      <streams>00000001</streams>
    </blackoutInfo>
    <title lang="sr"><![CDATA[Yoga retreat]]></title>
    <category lang="sr"><![CDATA[Entertainment]]></category>
    <icon src="default_playbill.png" ptype="3" />
    <episode-num system="xmltv_ns">0.0.0</episode-num>
  </programme>
  <programme ID="58136" start="20200528013000 +0200" stop="20200528030000 +0200" channel="XTV100006361" recordable="Y" npvrenable="Y" cpvrenable="N" type="program" deleted="false">
    <blackoutInfo>
      <isBlackout>1</isBlackout>
      <groupIDs>2</groupIDs>
      <streams>00000001</streams>
    </blackoutInfo>
    <title lang="sr"><![CDATA[Doctor Who]]></title>
    <category lang="sr"><![CDATA[Entertainment]]></category>
    <icon src="default_playbill.png" ptype="3" />
    <episode-num system="xmltv_ns">0.0.0</episode-num>
  </programme>
</tv>

желаемый результат, который я хотел бы, чтобы я получил следующие столбцы:

канал, начало, остановка, заголовок, категория

desired output

Ответы [ 2 ]

0 голосов
/ 29 мая 2020

Как указано @mzjn, для xml есть пространство имен по умолчанию; Вам придется использовать его в расчетах ур

import xml.etree.ElementTree as ET

def main():
    root = ET.parse("RTS_XTV100006361.xml")
    #declare namespace
    ns = '{http://www.xmltv.org/xmltv}'

    #required keys
    keys = ['channel','start','stop','type']
    box = []
    for ent in root.findall(f".//{ns}programme"):
        d = {key:value for key,value in ent.attrib.items() if key in keys}
        #attach title and category to dictionary
        d.update({"title" : ent.find(f".//{ns}title").text,
                  "category" : ent.find(f".//{ns}category").text
                 })
        box.append(d)

    return pd.DataFrame(box)

main()

           start                  stop               channel         type   title            category
0   20200528000000 +0200    20200528013000 +0200    XTV100006361    program Yoga retreat    Entertainment
1   20200528013000 +0200    20200528030000 +0200    XTV100006361    program Doctor Who      Entertainment
0 голосов
/ 29 мая 2020

В документе XML используется пространство имен по умолчанию (http://www.xmltv.org/xmltv).

Один из способов сделать то, что вы хотите, - использовать findall() и find() с подстановочным знаком ({*}) для пространство имен. Это работает с Python 3,8 .

import xml.etree.ElementTree as et
import pandas as pd

def getvalueofnode(node):
    return node.text if node is not None else None

def main():
    parsed_xml = et.parse("RTS_XTV100006361.xml")
    dfcols = ['start', 'stop', 'channel', 'type', 'title', 'category']
    df_xml = pd.DataFrame(columns=dfcols)

    for programme in parsed_xml.findall("{*}programme"):
        start = programme.get('start')
        stop = programme.get('stop')
        channel = programme.get('channel')
        type = programme.get('type')

        title = programme.find('{*}title')
        category = programme.find('{*}category')

        df_xml = df_xml.append(
            pd.Series([start, stop, channel, type,
                       getvalueofnode(title), getvalueofnode(category)], index=dfcols),
            ignore_index=True)

    pd.options.display.width = 0
    print (df_xml)

main()

Результат:

                  start                  stop       channel     type         title       category
0  20200528000000 +0200  20200528013000 +0200  XTV100006361  program  Yoga retreat  Entertainment
1  20200528013000 +0200  20200528030000 +0200  XTV100006361  program    Doctor Who  Entertainment
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...