Python + Expat: ошибка в & # 0;юридические лица - PullRequest
5 голосов
/ 14 июня 2010

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

#!/usr/bin/env python2.5

import doctest
from xml.etree import ElementTree
from StringIO import StringIO

def parse_xml_etree(sin, xpath):
  """
Takes as input a stream containing XML and an XPath expression.
Applies the XPath expression to the XML and returns a generator
yielding the text contents of each element returned.

>>> parse_xml_etree(
...   StringIO('<test><elem1>one</elem1><elem2>two</elem2></test>'),
...   '//elem1').next()
'one'
>>> parse_xml_etree(
...   StringIO('<test><elem1>one</elem1><elem2>two</elem2></test>'),
...   '//elem2').next()
'two'
>>> parse_xml_etree(
...   StringIO('<test><null>&#0;</null><elem3>three</elem3></test>'),
...   '//elem2').next()
'three'
"""

  tree = ElementTree.parse(sin)
  for element in tree.findall(xpath):
    yield element.text  

if __name__ == '__main__':
  doctest.testmod(verbose=True)

Третий тест завершается неудачей со следующим исключением:

ExpatError: ссылка на недопустимый номер символа: строка 1, столбец 13

Является ли объект &#0; недопустимым XML?Независимо от того, есть это или нет, файлы, которые я хочу проанализировать, содержат его, и мне нужен какой-то способ их проанализировать.Любые предложения для другого парсера, кроме Expat, или настройки для Expat, которые позволили бы мне это сделать?


Обновление: я обнаружил BeautifulSoup только сейчас, парсер супа тега, как отмечалосьниже, в ответном комментарии, и для забавы я вернулся к этой проблеме и попытался использовать ее как XML-очиститель перед ElementTree, но он покорно преобразовал &#0; в недопустимый нулевой байт.: -)

cleaned_s = StringIO(
  BeautifulStoneSoup('<test><null>&#0;</null><elem3>three</elem3></test>',
                     convertEntities=BeautifulStoneSoup.XML_ENTITIES
  ).renderContents()
)
tree = ElementTree.parse(cleaned_s)

... приводит к

xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 12

В моем конкретном случае мне не нужен был разбор XPath как таковой, я мог бы пойти с самой BeautifulSoupи его довольно простой стиль адресации узлов parsed_tree.test.elem1.contents[0].

Ответы [ 2 ]

6 голосов
/ 14 июня 2010

&#0; не входит в диапазон допустимых символов , определенный спецификацией XML.Увы, мои навыки в Python довольно просты, поэтому я не сильно помогаю там.

4 голосов
/ 14 июня 2010

&#0; не является допустимым символом XML.В идеале вы должны были бы заставить создателя файла изменить свой процесс так, чтобы файл не был недействительным, как этот.

Если вы должны принять эти файлы, вы можете предварительно обработать их, чтобы включить &#0 во что-то еще.Например, выберите @ в качестве escape-символа, превратите «@» в «@@», а «&#0;» в «@ 0».

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

...