Python xml.sax的parseString解析XML字符串报ExpatParser属性错误
错误原因
你遇到的'ExpatParser' object has no attribute 'processingInstruction'报错,是因为xml.sax.parseString的参数传递错误:parseString的第二个参数要求传入SAX内容处理器(ContentHandler)实例,而你传入了用make_parser()生成的解析器对象。
解析本地文件时你调用的是解析器自身的parse()方法,该方法内部会自动绑定默认的内容处理器,所以可以正常运行;但调用parseString时传入解析器对象后,底层Expat解析器找不到对应的事件回调方法,就会抛出属性不存在的异常。
修复方案
方案1:复用解析器逻辑,包装字符串为字节流
不需要额外调用parseString,将XML字符串包装为类文件字节流,直接用解析器的parse方法处理即可,改动量最小:
from xml.sax import make_parser import io import os filename = os.path.join('.', 'data', 'data.xml') xmlstr = "<note>\n<to>Mary</to>\n<from>Jane</from>\n<heading>Reminder</heading>\n<body>Go to the zoo</body>\n</note>" def parsefile(file): parser = make_parser() parser.parse(file) def parsestr(xmlstr): parser = make_parser() # 将字符串编码后包装为字节流,和解析本地文件逻辑完全一致 parser.parse(io.BytesIO(xmlstr.encode('utf-8'))) if __name__ == "__main__": try: parsefile(filename) print("%s is well-formed" % filename) except Exception as e: print("%s is NOT well-formed! %s" % (filename, e)) try: parsestr(xmlstr) print("%s is well-formed" % ('xml string')) except Exception as e: print("%s is NOT well-formed! %s" % ('xml string', e))
运行后两个校验场景都会正常通过。
方案2:正确传参调用parseString
如果要使用parseString接口,直接传入ContentHandler实例即可,不需要手动创建解析器。做基础格式校验时,用默认空实现的ContentHandler就足够:
from xml.sax import parse, parseString from xml.sax.handler import ContentHandler import os filename = os.path.join('.', 'data', 'data.xml') xmlstr = "<note>\n<to>Mary</to>\n<from>Jane</from>\n<heading>Reminder</heading>\n<body>Go to the zoo</body>\n</note>" def parsefile(file): parse(file, ContentHandler()) def parsestr(xmlstr): parseString(xmlstr.encode('utf-8'), ContentHandler()) # 后续try-catch校验逻辑和之前一致即可
更轻量的校验方案
如果你只需要做XML格式合法性校验,不需要SAX的流式事件解析能力,可以直接用标准库的xml.etree.ElementTree,代码更简洁,只要解析过程不抛出ParseError就说明XML格式合法:
import xml.etree.ElementTree as ET def check_xml_valid(xml_content: str) -> bool: try: ET.fromstring(xml_content) return True except ET.ParseError: return False
注意:Python标准库自带的XML解析模块都不支持防御外部实体注入,如果要处理不可信来源的XML内容,建议使用defusedxml等安全的第三方解析库。
内容的提问来源于stack exchange,提问作者Georg Pfolz
相关产品推荐
相关产品推荐

