Python: создание различных файловых объектов при чтении файла - PullRequest
1 голос
/ 14 июня 2011

Я читаю большой файл, содержащий различные элементы <xml>..</xml>.Поскольку у каждого XML-анализатора есть проблемы с этим, я хотел бы эффективно создавать новые файловые объекты для каждого <xml>..</xml> блока.

Я начинал создавать подкласс файлового объекта в Python, но застрял там.Я думаю, мне нужно перехватить каждую строку, начинающуюся с </xml>, и вернуть новый объект файла;может быть, используя yield.

Может ли кто-нибудь направить меня в правильном направлении?

Вот мой текущий фрагмент кода:

#!/bin/bash/env python

from lxml import etree
from StringIO import StringIO

class handler(file):
  def __init__(self, name, mode):
    file.__init__(self, name, mode)

  def next(self):
    return file.next(self)

  def listXmls(self):
    output = StringIO()
    line = self.next()
    while line is not None:
      output.write(line.strip())
      if line.strip() == '</xml>':
        yield output
        output = StringIO()
      try:
        line = self.next()
      except StopIteration:
        break
    output.close()

f = handler('myxml.xml', 'r')
for elem in f.listXmls():
  print 'm' + elem.getvalue() + 'm'
  context = etree.iterparse(elem, events=('end',), tag='id')
  for event, element in context:
    print element.tag

Спасибо!

РЕШЕНИЕ (все еще интересует лучшая версия):

#!/bin/bash/env python

from lxml import etree
from StringIO import StringIO

class handler(file):
  def __init__(self, name, mode):
    file.__init__(self, name, mode)

  def next(self):
    return file.next(self)

  def listXmls(self):
    output = StringIO()
    output.write(self.next())
    line = self.next()
    while line is not None:
      if line.startswith('<?xml'):
        output.seek(0)
        yield output
        output = StringIO()
      output.write(line)
      try:
        line = self.next()
      except StopIteration:
        break
    output.seek(0)
    yield output

f = handler('myxml.xml', 'r')
for elem in f.listXmls():
  context = etree.iterparse(elem, events=('end',), tag='id')
  for event, element in context:
    print element.tag

1 Ответ

1 голос
/ 14 июня 2011

Хотя это и не прямой ответ на ваш вопрос, это может решить вашу проблему в любом случае: простое добавление еще одного <xml> в начале и еще одного </xml> в конце, вероятно, заставит ваш XML-анализатор принять документ:

from lxml import etree
document = "<xml>a</xml> <xml>b</xml>"
document = "<xml>" + document + "</xml>"
for subdocument in etree.XML(document):
    # whatever
...