Во-первых, не беспокойтесь о чтении и записи файла, вы можете создать файлоподобный объект, который обернет ваш открытый файл и обработает данные, прежде чем они будут обработаны синтаксическим анализатором. Во-вторых, ваша буферизация может просто позаботиться о концах прочитанных байтов. Вот некоторый рабочий код:
class Wrapped(object):
def __init__(self, f):
self.f = f
self.buffer = ""
def read(self, size=0):
buf = self.buffer + self.f.read(size)
buf = buf.replace("!", "!!")
buf = re.sub(r"&(#x[0-9a-fA-F]+;)", r"!\1", buf)
# If there's an ampersand near the end, hold onto that piece until we
# have more, to be sure we don't miss one.
last_amp = buf.rfind("&", -10, -1)
if last_amp > 0:
self.buffer = buf[last_amp:]
buf = buf[:last_amp]
else:
self.buffer = ""
return buf
Затем в вашем коде замените это:
it = ET.iterparse(file(xml, "rb"))
с этим:
it = ET.iterparse(Wrapped(file(xml, "rb")))
В-третьих, я использовал замену, заменяя «&» на «!» И «!» с "!!", так что вы можете исправить их после разбора, и вы не рассчитываете на непонятные последовательности. В конце концов, это данные переполнения стека, поэтому множество странных случайных знаков препинания может произойти естественным образом.