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

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

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?

Ответы [ 3 ]

12 голосов
/ 02 марта 2011

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

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

Вы можете попробоватьврать и помещать XHTML DTD в ваш документ.например,

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>'
6 голосов
/ 03 марта 2011

@ Алекс прав: ваш документ не является правильно сформированным 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-документы были правильно сформированы.

0 голосов
/ 29 марта 2015

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

...