Подтвердить что ты не робот

Каков наилучший способ обработки -подобных объектов в XML-документах с помощью lxml?

Рассмотрим следующее:

from lxml import etree
from StringIO import StringIO

x = """<?xml version="1.0" encoding="utf-8"?>\n<aa>&nbsp;&acirc;</aa>"""
p = etree.XMLParser(remove_blank_text=True, resolve_entities=False)
r = etree.parse(StringIO(x), p)

Это не получится:
lxml.etree.XMLSyntaxError: Entity 'nbsp' not defined, line 2, column 11

Это потому, что resolve_entities=False не игнорирует их, он просто не разрешает их.

Если я использую etree.HTMLParser вместо этого, он создает теги html и body, а также множество других специальных действий, которые он пытается сделать для html.

Каков наилучший способ получить дочерний текст &nbsp;&acirc; в теге aa с помощью lxml?

4b9b3361

Ответ 1

Вы не можете игнорировать объекты, поскольку они являются частью определения XML. Ваш документ не является корректным, если он не имеет DTD или standalone = "yes", или если он включает в себя объекты без определения сущности в DTD. Ложь и заявка на ваш документ HTML.

https://mailman-mail5.webfaction.com/pipermail/lxml/2008-February/003398.html

Вы можете попробовать лежать и поставить DTD XHTML в свой документ. например.

from lxml import etree
try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO
x = """<?xml version="1.0" encoding="utf-8"?>\n<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >\n<aa>&nbsp;&acirc;</aa>"""
p = etree.XMLParser(remove_blank_text=True, resolve_entities=False)
r = etree.parse(StringIO(x), p)
etree.tostring(r) # '<aa>&nbsp;&acirc;</aa>'

Ответ 2

@Alex прав: ваш документ не является правильно сформированным XML, и поэтому синтаксические анализаторы XML не будут анализировать его. Одним из вариантов является предварительная обработка текста документа для замены поддельных объектов их символами utf-8:

entities = [
    ('&nbsp;', u'\u00a0'),
    ('&acirc;', u'\u00e2'),
    ...
    ]

for before, after in entities:
    x = x.replace(before, after.encode('utf8'))

Конечно, это может быть нарушено также довольно странным "xml".

Лучше всего исправить ваши входные XML-документы, чтобы быть хорошо сформированным XML.

Ответ 3

Когда я пытался сделать что-то подобное, я просто использовал x.replace('&', '&amp;') перед разбором строки.