Разделение большого XML-файла на несколько файлов с помощью Beautifulsoup - PullRequest
2 голосов
/ 05 июня 2019

Я пытаюсь разбить большой XML-файл на более мелкие, сначала я начал с Beautifulsoup:

from bs4 import BeautifulSoup
import os
# Core settings
rootdir = r'C:\Users\XX\Documents\Grant Data\2010_xml'
extension = ".xml"
to_save = r'C:\Users\XX\Documents\all_patents_as_xml'

index = 0
for root, dirs, files in os.walk(rootdir):
    for file in files:
        if file.endswith(extension):
            print(file)
            file_name = os.path.join(root,file)
            with open(file_name) as f:
                data = f.read()
            texts = data.split('?xml version="1.0" encoding="UTF-8"?')
            for text in texts:
                index += 1
                filename = to_save + "\\"+ str(index) + ".txt"
                with open(filename, 'w') as f:
                    f.write(text)

Однако я получил ошибку памяти. Затем я переключился на xml etree:

from xml.etree import ElementTree as ET
import re


file_name = r'C:\Users\XX\Documents\Grant Data\2010_xml\2010cat_xml.xml'


with open(file_name) as f:
    xml = f.read()
tree = ET.fromstring(re.sub(r"(<\?xml[^>]+\?>)", r"\1<root>", xml) + "</root>")
parser = ET.iterparse(tree)
to_save = r'C:\Users\Yilmaz\Documents\all_patents_as_xml'
index = 0
for event, element in parser:
    # element is a whole element
    if element.tag == '?xml version="1.0" encoding="UTF-8"?':
        index += 1
        filename = to_save + "\\"+ str(index) + ".txt"
        with open(filename, 'w') as f:
            f.write(ET.tostring(element))
        # do something with this element
        # then clean up
        element.clear()

и я получаю следующую ошибку:

OverflowError: size does not fit in an int

Я использую операционную систему Windows, я знаю, что в Linux вы можете отделить xmls от потребителя, но в моем случае я не знаю, что делать.

Ответы [ 2 ]

1 голос
/ 19 июня 2019

Существуют серьезные проблемы с вашим вопросом и вашими попытками его решения:

  1. Вы упомянули, что используете Beautiful Soup. Однако, хотя вы импортируете Beautiful Soup в свой код, вы на самом деле ничего не делаете с этим .

  2. Код, который вы показываете, который использует xml.etree, абсолютно неверен. В строке parser = ET.iterparse(tree), tree - это дерево XML, уже проанализированное с ET.fromstring, но аргумент iterparse должен быть либо именем файла , либо объектом файла, Дерево XML не является ни тем, ни другим. Так что эта попытка мертва по прибытии.

Но, что более важно, похоже, что вы пытаетесь обработать файл, который содержит несколько сцепленных XML-файлов. В вашей xml.etree попытке у вас есть этот тест:

element.tag == '?xml version="1.0" encoding="UTF-8"?'

Единственное намерение, которое я могу себе представить для этого теста, заключается в том, что вы думаете, что xml.etree будет каким-то образом интерпретировать <?xml version="1.0" encoding="UTF-8"?> как элемент XML с именем '?xml version="1.0" encoding="UTF-8"?'. Однако структура <?xml version="1.0" encoding="UTF-8"?> - это не элемент XML , а декларация XML .

И так как ваш код, кажется, пытается разделить каждый раз, когда встречается объявление XML, кажется, что ваши входные данные - это файл, который содержит несколько объявлений XML. Этот файл не является допустимым XML. Спецификация XML позволяет объявлению XML появляться один раз, и только один раз в начале файла XML. (Не путайте объявление XML с инструкцией обработки. Они выглядят одинаково, поскольку оба они разделены <? и ?>, но объявление XML не является инструкцией обработки.) Если вы используете анализатор XML на входе файл, и этот синтаксический анализатор соответствует спецификации XML, затем он должен отклонить ваш файл как не XML, потому что XML не позволяет объявлениям XML появляться в документах в произвольном порядке.

Где это тебя оставляет? Если все декларации XML, присутствующие в вашем исходном документе, одинаковы, существует относительно простой способ сделать ваш документ анализируемым с помощью анализатора XML. (Попытки, которые вы сделали, предполагают, что они все одинаковы, так как вы не используете регулярные выражения для сопоставления с различными формами декларации XML (например, с указанием параметра standalone).) Вы можете просто удалить all XML-декларации из вашего исходного документа, оберните его в новый корневой элемент и проанализируйте его с помощью xml.etree. (Это предполагает, что отдельные XML-документы, которые были объединены для создания исходного документа, были все по отдельности правильно сформированы. Если это не так, это не сработает.)

Обратите внимание, однако, что строка <?xml version="1.0" encoding="UTF-8"?> может появляться в документе XML в тех случаях, когда эта строка на самом деле не является декларацией XML. Вот правильно сформированный XML-документ, который отбрасывает алгоритм, который просто ищет строку, похожую на объявление XML:

<?xml version = "1.0" encoding = "UTF-8"?>
<a>
  <![CDATA[
           <?xml version = "1.0" encoding = "UTF-8"?>
  ]]>
  <?q <?xml version = "1.0" encoding = "UTF-8"?> ?>
  <!-- <?xml version = "1.0" encoding = "UTF-8"?> -->
</a>

Если вы знаете, как был создан ваш исходный файл, возможно, вы уже наверняка знаете, что у вас нет ни одного из указанных выше случаев. В противном случае вы можете проверить свой источник и убедиться, что ничего из вышеперечисленного не произошло.

Как только вы позаботитесь об этом, тогда сработает стратегия, основанная на ET.iterparse, или SAX.

1 голос
/ 06 июня 2019

Если ваш XML не может быть загружен из-за ограничений памяти, вам следует рассмотреть возможность использования SAX .

С помощью SAX вы будете читать «маленькие кусочки» документа и делать с ними все, что захотите (Пример: сохранить все N элементов в новый файл).

Python SAX пример 1 .

Python SAX пример 2 .

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