Моя интерпретация ваших потребностей заключается в том, что вы хотите иметь возможность анализировать частичный файл и выстраивать структуру документа на ходу.Я взял некоторые предположения из файла, который вы загрузили:
По сути, вы хотите анализировать коллекции вещей, которые имеют схожие свойства - я понимаю это из того, как вы представили желаемоевывод в виде таблицы со строками, содержащими значения.
Вы ожидаете, что эти наборы вещей будут иметь одинаковое количество значений.
Вам нужночтобы иметь возможность анализировать частичные файлы.
Вы не беспокоитесь о свойствах элементов, а только об их содержимом.
Я использую xml.sax
, поскольку это касаетсяпроизвольно большие файлы и не нужно читать весь файл в память.Обратите внимание, что стратегия, которой я сейчас следую, на самом деле не так хорошо масштабируется, так как я храню все элементы в памяти для построения кадра данных, но вы также можете вывести пути и содержимое.
InВ примере файла существует проблема с наличием одной строки на Item
, поскольку есть кратные значения тега Genre
, а также несколько тегов Product
.Я обработал повторяющиеся теги Genre
, добавив их.Это зависит от тегов жанра, появляющихся последовательно.Не совсем понятно, как отношения Product
могут обрабатываться в одной таблице.
import xml.sax
from collections import defaultdict
class StructureParser(xml.sax.handler.ContentHandler):
def __init__(self):
self.text = ''
self.path = []
self.datalist = defaultdict(list)
self.previouspath = ''
def startElement(self, name, attrs):
self.path.append(name)
def endElement(self, name):
strippedtext = self.text.strip()
path = '/'.join(self.path)
if strippedtext != '':
if path == self.previouspath:
# This handles the "Genre" tags in the sample file
self.datalist[path][-1] += f',{strippedtext}'
else:
self.datalist[path].append(strippedtext)
self.path.pop()
self.text = ''
self.previouspath = path
def characters(self, content):
self.text += content
Вы бы использовали это так:
parser = StructureParser()
try:
xml.sax.parse('uyalicihow.xml', parser)
except xml.sax.SAXParseException:
print('File probably ended too soon')
Это будет читатьфайл примера просто в порядке.
Как только он прочитает и, вероятно, напечатает «Файл, вероятно, скоро закончится», вы проанализируете содержимое в parser.datalist
.
Вы, очевидно, хотите иметь только те части, которые успешно читаются, поэтому вы можете составить кратчайший список и построить DataFrame только с этими путями:
import pandas as pd
smallest_items = min(len(e) for e in parser.datalist.values())
df = pd.DataFrame({key: value for key, value in parser.datalist.items() if len(value) == smallest_items})
Это дает что-то похожее на вашжелаемый результат:
Items/Item/Main/Platform Items/Item/Main/PlatformID Items/Item/Main/Type
0 iTunes 353736518 TVEpisode
1 iTunes 495275084 TVEpisode
Столбцы для тестового файла, которые соответствуют здесь,
>> df.columns
Index(['Items/Item/Main/Platform', 'Items/Item/Main/PlatformID',
'Items/Item/Main/Type', 'Items/Item/Main/TVSeriesID',
'Items/Item/Info/BaseURL', 'Items/Item/Info/EpisodeNumber',
'Items/Item/Info/HighestResolution',
'Items/Item/Info/LanguageOfMetadata', 'Items/Item/Info/LastModified',
'Items/Item/Info/Name', 'Items/Item/Info/ReleaseDate',
'Items/Item/Info/ReleaseYear', 'Items/Item/Info/RuntimeInMinutes',
'Items/Item/Info/SeasonNumber', 'Items/Item/Info/Studio',
'Items/Item/Info/Synopsis', 'Items/Item/Genres/Genre',
'Items/Item/Products/Product/URL'],
dtype='object')
На основании ваших комментариев кажется, что для вас более важно иметь всеэлементы представлены, но, возможно, просто показывают предварительный просмотр, и в этом случае вы можете использовать только первые элементы из данных.Обратите внимание, что в этом случае записи Product
s не будут соответствовать записям Item
.
df = pd.DataFrame({key: value[:smallest_items] for key, value in parser.datalist.items()})
Теперь мы получаем все пути:
>> df.columns
Index(['Items/Item/Main/Platform', 'Items/Item/Main/PlatformID',
'Items/Item/Main/Type', 'Items/Item/Main/TVSeriesID',
'Items/Item/Info/BaseURL', 'Items/Item/Info/EpisodeNumber',
'Items/Item/Info/HighestResolution',
'Items/Item/Info/LanguageOfMetadata', 'Items/Item/Info/LastModified',
'Items/Item/Info/Name', 'Items/Item/Info/ReleaseDate',
'Items/Item/Info/ReleaseYear', 'Items/Item/Info/RuntimeInMinutes',
'Items/Item/Info/SeasonNumber', 'Items/Item/Info/Studio',
'Items/Item/Info/Synopsis', 'Items/Item/Genres/Genre',
'Items/Item/Products/Product/URL',
'Items/Item/Products/Product/Offers/Offer/Price',
'Items/Item/Products/Product/Offers/Offer/Currency'],
dtype='object')