я написал небольшую функцию, которая использует ElementTree и XPath для извлечения текстового содержимого определенных элементов в файле XML:Python + Expat: Ошибка на лиц
#!/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>�</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
ли �
организации незаконной XML? Независимо от того, является это или нет, файлы, которые я хочу проанализировать, содержат его, и мне нужно каким-то образом их проанализировать. Любые предложения для другого парсера, чем Expat, или настройки для Expat, которые позволили бы мне это сделать?
Обновление: Я обнаружил BeautifulSoup только сейчас, а тег суп анализатор, как указано ниже в ответ комментарии, и для удовольствия я вернулся к этой проблеме и попытался использовать его в качестве XML-уборщика перед ElementTree , но он покорно преобразовал �
в байт с нулевым недопустимым значением. :-)
cleaned_s = StringIO(
BeautifulStoneSoup('<test><null>�</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]
.
Хм, да, спецификация делает это совершенно ясным. Спасибо за точную ссылку. – clacke
Я понимаю, что это старый поток, но спецификация говорит, что * буквальные * символы могут появляться только в XML. Последовательность байтов не * буквально * нулевой символ, а 4-символьная последовательность, которая * представляет * нулевой байт. Учитывая это различие, является legal? Я не могу найти ничего в спецификации, которая говорит *, что * является незаконным. –
Действительный вопрос. Но ответ здесь: http://www.w3.org/TR/REC-xml/#sec-references говорит: «Символы, ссылающиеся на использование ссылок на символы, должны соответствовать произведению для Char». – clacke