Разбор файла xml и подача списка объектов с полученными данными. - PullRequest
0 голосов
/ 24 февраля 2020

РЕДАКТИРОВАТЬ: Добавлено рабочее решение для обзора в нижней части поста.

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

Вот сцена: у меня есть xml документ, в котором перечислены игры и каждый игра, как некоторые атрибуты (или дочерние узлы? Я не уверен, на самом деле). Я хочу:

For each game:
 Gets it's path, name, and genre
 Build a Game object with this
 Store the object in an array list

Я понимаю команду "findall", но не понимаю, как связать данные между ними. Поскольку это дерево, я полагаю, что мне нужно просто переходить от игры к игре, получать нужные мне данные и переходить к следующей игре, но, черт возьми, я застрял.

Итак, вот извлечение файла xml, который мне нужно проанализировать:

<?xml version="1.0"?>
<gameList>
    <provider>
        <System>Megadrive</System>
        <software>Skraper</software>
        <database>ScreenScraper.fr</database>
        <web>http://www.screenscraper.fr</web>
    </provider>
    <game id="574" source="ScreenScraper.fr">
        <path>./3 Ninjas Kick Back.zip</path>
        <name>3 Ninjas Kick Back</name>
        <genre>Platform-Action</genre>
    </game>
    <game id="394" source="ScreenScraper.fr">
        <path>./688 Attack Sub.zip</path>
        <name>688 Attack Sub</name>
        <genre>Simulation</genre>
    </game>
</gameList>

Вот мой текущий код в песочнице, состояние попытки и проверки:

import os
from xml.etree import ElementTree


class GameListParser:
    GAMELIST_FILE = 'gamelist.xml'

    GAMELIST_KEY = "gameList"
    GAME_KEY = "game"
    GENRE_KEY = "genre"
    PATH_KEY = "path"
    NAME_KEY = "name"

    keys_map = {
        GAMELIST_KEY: {
            GAME_KEY: [NAME_KEY, GENRE_KEY, PATH_KEY]
        }
    }

    def __init__(self, gamelist_path):
        self.gamelist = os.path.join(gamelist_path, self.GAMELIST_FILE)
        self.parsed_gamelist = None
        self.__parse()

    def __parse(self):
        self.parsed_gamelist = ElementTree.parse(self.gamelist)

    def __get_root(self):
        return self.parsed_gamelist.getroot()

    def get_all_games(self):
        return self.parsed_gamelist.findall(self.GAME_KEY)

    def print_games_details(self):
        for node in self.get_all_games():
            for game in node.getiterator():
                name = game.attrib.get(self.NAME_KEY)
                genre = game.attrib.get(self.GENRE_KEY)

С print_games_details метод, я просто надеюсь напечатать игровые данные, но на самом деле узел и игровой объект одинаковы, поэтому имя и жанр - Нет, и я не получаю нужные мне данные.

Я почти уверен, что это так просто, но мне приходилось работать с xml только 3-4 раза в жизни, единственный раз, когда мне приходилось разбирать объекты, был C ++, и это был полный системный рефакторинг. Два других раза были в Matlab и Python в направлении объектов к xml файлу. Каждый раз, когда у меня возникают проблемы, я не могу asp обойти логи c дерева, как разобрать / создать их, и онлайн-ресурсы мне мало помогают.

РЕДАКТИРОВАТЬ: Итак, я Я работал над решением, и хотя оно дает мне результат, я ожидаю, что мне это совсем не удобно. Моя проблема в том, что это решение подразумевает, что я очень хорошо знаю структуру файла xml, когда я просто прошёл его.

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

. Если кто-то из вас мог бы любезно просмотреть следующий код и предоставить обратную связь и улучшения, я был бы очень признателен за это:

1 Ответ

1 голос
/ 24 февраля 2020

Рекомендую стороннюю библиотеку: SimplifiedDo c. pip install -U Simpified_scrapy

from simplified_scrapy import SimplifiedDoc
html = '''
<?xml version="1.0"?>
<gameList>
    <provider>
        <System>Megadrive</System>
        <software>Skraper</software>
        <database>ScreenScraper.fr</database>
        <web>http://www.screenscraper.fr</web>
    </provider>
    <game id="574" source="ScreenScraper.fr">
        <path>./3 Ninjas Kick Back.zip</path>
        <name>3 Ninjas Kick Back</name>
        <genre>Platform-Action</genre>
    </game>
    <game id="394" source="ScreenScraper.fr">
        <path>./688 Attack Sub.zip</path>
        <name>688 Attack Sub</name>
        <genre>Simulation</genre>
    </game>
</gameList>
'''
doc = SimplifiedDoc(html)
games = doc.gameList.games
datas = [[g.path.text,g.name.text,g.genre.text] for g in games]
print (datas)

Результат:

[['./3 Ninjas Kick Back.zip', '3 Ninjas Kick Back', 'Platform-Action'], ['./688 Attack Sub.zip', '688 Attack Sub', 'Simulation']]

Вот еще примеры: https://github.com/yiyedata/simplified-scrapy-demo/tree/master/doc_examples

...