Python 有没有办法强制lxml解析在标记中指定编码的Unicode字符串?

Python 有没有办法强制lxml解析在标记中指定编码的Unicode字符串?,python,lxml,Python,Lxml,我有一个指定编码的XML文件,我使用UnicodeAmmit将其转换为unicode(出于存储的原因,我不能将其存储为字符串)。我稍后将其传递给lxml,但它拒绝忽略文件中指定的编码并将其解析为Unicode,因此引发了一个异常 如何强制lxml解析文档?这种行为似乎过于严格。基本上,解决方案是: if isinstance(mystring, unicode): mystring = mystring.encode("utf-8") 真的。干得好,lxml 编辑:结果是,在本例中,l

我有一个指定编码的XML文件,我使用UnicodeAmmit将其转换为unicode(出于存储的原因,我不能将其存储为字符串)。我稍后将其传递给lxml,但它拒绝忽略文件中指定的编码并将其解析为Unicode,因此引发了一个异常


如何强制lxml解析文档?这种行为似乎过于严格。

基本上,解决方案是:

if isinstance(mystring, unicode):
    mystring = mystring.encode("utf-8")
真的。干得好,lxml


编辑:结果是,在本例中,lxml自动错误地检测编码。似乎我必须手动搜索并从页面中删除“字符集”和“编码”。

您无法从unicode字符串中解析,并且在字符串中有编码声明。 因此,您可以将其设置为编码字符串(因为您显然无法将其存储为字符串,因此必须在解析之前对其进行重新编码。或者您自己使用lxml将树序列化为unicode:
etree.tostring(tree,encoding=unicode)
,而无需xml声明。您可以使用etree.fromunicode轻松地再次解析结果

编辑:显然,如果您已经拥有unicode字符串,并且无法控制该字符串的生成方式。您必须再次对其进行编码,并向解析器提供您使用的编码:

utf8_parser = etree.XMLParser(encoding='utf-8')

def parse_from_unicode(unicode_str):
    s = unicode_str.encode('utf-8')
    return etree.fromstring(s, parser=utf8_parser)

这将确保忽略xml声明中的任何内容,因为解析器将始终使用utf-8。

解决方案不是重新编码字符串。字符串中的编码声明可以表示UTF8以外的内容。不要盲目地重新编码到UTF8,并期望它一直工作

解决方案是去掉编码声明。您手头已经有了unicode字符串,不再需要它了

# this is from lxml/apihelpers.pxi
RE_XML_ENCODING = re.compile(
    ur'^(<\?xml[^>]+)\s+encoding\s*=\s*["\'][^"\']*["\'](\s*\?>|)', re.U)

RE_XML_ENCODING.sub("", broken_xml_string, count=1)
#这来自lxml/apihelpers.pxi
RE_XML_ENCODING=RE.compile(
ur'^(]+)\s+编码\s*=\s*[“\']”[^“\']”]*[“\']”(\s*\?>)”,re.U)
RE_XML_ENCODING.sub(“”,断开的_XML_字符串,计数=1)
这里最糟糕的情况(没有找到xml编码声明)是O(n),这非常糟糕(但仍然比盲目编码为二进制要好),所以我愿意接受这里的建议

PS:xml编码问题的一些有趣分析:


我有一个现有的实现,我需要一个树。 我在meta标记中也遇到了一个问题。将resolve_entities设置为false修复了该问题

opener=urllib.request.build\u opener()
response=opener.open(url['url'])
raw_page=response.read()
答复:close()
已解析页面=原始页面。替换(b'encoding=“UTF-8”,b'')
解析页面=StringIO(解析页面解码('ASCII'))
parser=ET.XMLParser(resolve_entities=False,encoding=“ASCII”)
tree=ET.parse(已解析的页面,解析器)
root=tree.getroot()

整个问题是,我一开始无法得到一棵树,如果可以的话,我不会有任何问题…@Stavros Korokithakis,etree是模块,不是解析的树。@Daniel Kluev:是的,但是“树”"是一棵树。@Steven:关于你的编辑,应该可以,谢谢。最后,我从lxml中提取了编码检测正则表达式,并用它从文件中去除编码。由于它很早就失败了,我认为它应该是最快的。这个解决方案是错误的。不要盲目地编码到utf8。文档中的编码声明很可能是utf16或其他东西。解决方案是去掉编码声明,因为它不再需要了--您已经有了一个unicode字符串!如果您给匹配运算符如+和*一个限制,将它们替换为{,100},那么长字符串的最坏情况复杂度远小于O(整个字符串长度).然而,在最坏的情况下成功的几率似乎很小!