Разделение большого XML-файла в Python - PullRequest
9 голосов
/ 25 января 2009

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

Моя проблема состоит в том, чтобы найти чистый способ отметить начало и конец тегов, чтобы я мог захватить текст внутри при сканировании файла с помощью "for line in f"

Я бы предпочел не использовать часовые переменные. Есть ли питонский способ сделать это?

Файл слишком большой для чтения в память.

Ответы [ 5 ]

9 голосов
/ 25 января 2009

Существует два распространенных способа обработки данных XML.

Один из них называется DOM, что означает объектную модель документа. Этот стиль синтаксического анализа XML, вероятно, является тем, что вы видели, просматривая документацию, поскольку он считывает весь XML в память для создания объектной модели.

Второй называется SAX, который является методом потоковой передачи. Парсер начинает читать XML и отправляет в ваш код сигналы об определенных событиях, например, когда новый стартовый тег найден.

Итак, SAX - это то, что вам нужно для вашей ситуации. Sax-парсеры можно найти в библиотеке python в xml.sax и xml.parsers.expat .

6 голосов
/ 28 января 2009

Я успешно справился с методом cElementTree.iterparse, чтобы выполнить аналогичную задачу.

У меня был большой документ XML с повторяющимися «записями» с тегом «resFrame», и я хотел отфильтровать записи для определенного идентификатора. Вот код, который я использовал для этого:

исходный документ имел такую ​​структуру

<snapDoc>
  <bucket>....</bucket>
  <bucket>....</bucket>
  <bucket>....</bucket>
  ...
  <resFrame><id>234234</id>.....</resFrame>
  <frame><id>344234</id>.....</frame>
  <resFrame>...</resFrame>
  <frame>...</frame>
</snapDoc>

Я использовал следующий сценарий для создания меньшего документа, который имел ту же структуру, записи сегмента и только записи resFrame с определенным идентификатором.

#!/usr/bin/env python2.6

import xml.etree.cElementTree as cElementTree
start = '''<?xml version="1.0" encoding="UTF-8"?>
<snapDoc>'''

def main():
    print start
    context = cElementTree.iterparse('snap.xml', events=("start", "end"))
    context = iter(context)
    event, root = context.next() # get the root element of the XML doc

    for event, elem in context:
        if event == "end":
            if elem.tag == 'bucket': # i want to write out all <bucket> entries
               elem.tail = None  
               print cElementTree.tostring( elem )
            if elem.tag == 'resFrame':
                if elem.find("id").text == ":4:39644:482:-1:1": # i only want to write out resFrame entries with this id
                    elem.tail = None
                    print cElementTree.tostring( elem )
            if elem.tag in ['bucket', 'frame', 'resFrame']:
                root.clear()  # when done parsing a section clear the tree to safe memory
    print "</snapDoc>"

main()
6 голосов
/ 25 января 2009

Вы можете рассмотреть использование функции ElementTree iterparse для этой ситуации.

1 голос
/ 25 января 2009

Как по счастливой случайности! Уилл Ларсон только что сделал хороший пост о Обработка очень больших файлов CSV и XML в Python .

Основным выводом, по-видимому, является использование модуля xml.sax, как упомянул Ван, и создание некоторых макро-функций для абстрагирования деталей низкоуровневого SAX API.

0 голосов
/ 02 июля 2009

Это старая, но очень хорошая статья из очень хорошего столбца Python & XMl от Uche Ogbuji. Он охватывает ваш точный вопрос и использует стандартный саксофон lib, как и предлагал другой ответ. Разложение, процесс, перекомпоновка

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