xml.parsers.expat– 使用Expat快速XML解析


警告

pyexpat模块不能抵御恶意构建的数据。如果需要解析不受信任或未经身份验证的数据,请参阅 XML漏洞.

xml.parsers.expat模块是Expatnon验证XML解析器的Python接口。该模块提供单个扩展类型xmlparser,表示XML解析器的当前状态。已经创建了Afferan xmlparser对象,可以将对象的各种属性设置为处理函数。然后,当XML文档被提供给分析器时,将为XML文档中的字符数据和标记调用处理函数.

该模块使用pyexpat模块来提供对Expatparser的访问。不推荐直接使用pyexpat模块.

这个模块提供了一个异常和一个类型对象:

exception xml.parsers.expat.ExpatError

当Expat报告错误时引发的异常。有关解释Expat错误的详细信息,请参阅 ExpatError Exceptions .

exception xml.parsers.expat.error

适用于ExpatError.

xml.parsers.expat.XMLParserType

来自的返回值的类型ParserCreate()功能。

xml.parsers.expat模块包含两个功能:

xml.parsers.expat.ErrorStringerrno

返回给定错误号的解释字符串errno.

xml.parsers.expat.ParserCreateencoding=None, namespace_separator=None

创建并返回一个新的xmlparser对象。encoding如果指定,则必须是一个字符串,用于命名XML数据使用的编码。Expat不支持与Python一样多的编码,并且其编码的所有功能都无法扩展;它支持UTF-8,UTF-16,ISO-8859-1(Latin1)和ASCII。如果encoding[1]它将覆盖文档的隐式或显式编码.

Expat可以选择为你做XML命名空间处理,通过为namespace_separator。该值必须是单字符字符串;如果字符串长度不合适,将会引发ValueErrorNone被认为与遗漏相同)。启用名称空间处理时,将扩展属于名称空间的元素类型名称和属性名称。传递给元素处理程序的元素名称StartElementHandlerEndElementHandler将是命名空间URI,命名空间分隔符和名称的本地部分的连接。如果命名空间分隔符是一个零字节(chr(0)),那么命名空间URI和本地部分将连接在一起而没有任何分隔符.

例如,如果namespace_separator设置为a空格字符(" ")并解析以下文档:

<?xml version="1.0"?><root xmlns    = "http://default-namespace.org/"      xmlns:py = "http://www.python.org/ns/">  <py:elem1 />  <elem2 xmlns="" /></root>

StartElementHandler将收到以下字符串的eachelement:

http://default-namespace.org/ roothttp://www.python.org/ns/ elem1elem2

由于Expat库的限制所使用的pyexpatxmlparser返回的实例只能用于解析单个XML文档。调用ParserCreate为每个文件提供uniqueparser实例.

参见

Expat XML Parser
Expat项目的主页.

XMLParser对象

xmlparser对象有以下方法:

xmlparser.Parsedata [, isfinal]

解析字符串data的内容,调用适当的处理函数来处理解析后的数据。isfinal在最后调用此方法时必须是真的;它允许在片段中解析单个文件,而不是提交多个文件.data可以随时为空字符串.

xmlparser.ParseFile (file

解析从对象file. file读取XML数据只需要提供read(nbytes)方法,当没有更多数据时返回空字符串

xmlparser.SetBase// (base

设置用于解析系统标识符声明中的相对URI的基数。解析相对标识符留给应用程序:thisvalue将作为baseExternalEntityRefHandler(), NotationDeclHandler()UnparsedEntityDeclHandler()函数的说法

xmlparser.GetBase// ()

返回包含前一次调用的基数的字符串到SetBase(),或None如果SetBase()没有被叫到.

xmlparser.GetInputContext ( )

以字符串形式返回生成当前事件的输入数据。数据是包含文本的实体的编码。当anvent handler未激活时调用,返回值为None.

xmlparser.ExternalEntityParserCreatecontext [, encoding]

创建一个“子”解析器,可用于解析由解析的内容提供的外部解析实体父解析器context参数应该是传递给ExternalEntityRefHandler()处理函数的字符串,如下所述。创建子解析器时将ordered_attributesspecified_attributes设置为该解析器的值.

xmlparser.SetParamEntityParsing (flag

控制参数实体的解析(包括外部DTD子集)。可能的flag值是XML_PARAM_ENTITY_PARSING_NEVER,XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONEXML_PARAM_ENTITY_PARSING_ALWAYS。如果设置标志成功,则返回true .

xmlparser.UseForeignDTD ( [flag])

使用flag(默认值)的真值调用它将导致Expat用ExternalEntityRefHandler调用None对于允许加载备用DTD的所有参数。如果文件不包含文档类型声明,ExternalEntityRefHandler仍然会被认定,但StartDoctypeDeclHandlerEndDoctypeDeclHandler将不会被调用.

传递flag的假值将取消之前通过true值的调用,否则无效.

这个方法只能在Parse()ParseFile()方法被调用;在调用了其中任何一个之后调用它会导致ExpatErrorcode属性设置为errors.codes[errors.XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING].

xmlparser的情况下被引发具有以下属性:

xmlparser.buffer_size

大小当buffer_text为true时使用的缓冲区。可以通过为此属性赋值新的整数值来设置新的缓冲区大小。当更改大小时,将刷新缓冲区.

xmlparser.buffer_text

设置此为true会导致xmlparser对象缓冲由Expat返回的textualcontent,以避免在可能的情况下多次调用CharacterDataHandler()回调。这可以大大提高性能,因为Expat通常会在每行结束时将字符数据分成chunksat。默认情况下,此属性为false,并且可以在任何时间更改.

xmlparser.buffer_used

如果启用了buffer_text,则缓冲区中存储的字节数。这些字节表示UTF-8编码的文本。当buffer_text为假时,该属性没有任何有意义的解释.

xmlparser.ordered_attributes

将此属性设置为非零整数会导致属性报告为列表而不是字典。属性以文档文本中的顺序显示。对于每个属性,提供了两个列表条目:属性名称和属性值。(此模块的旧版本也使用此格式。)默认情况下,此属性为false;它可以在任何时候更改.

xmlparser.specified_attributes

如果设置为非零整数,解析器将仅报告在文档实例中指定的那些属性,而不报告从属性声明派生的那些属性。设置此功能的应用程序需要特别注意使用声明中可用的附加信息,以符合XML处理器行为的标准。默认情况下,此属性为false;它可以在任何时候更改.

以下属性包含与最近的错误相关的值xmlparser对象,并且只有正确的值才能调用Parse()ParseFile()已经引发了xml.parsers.expat.ExpatError异常.

xmlparser.ErrorByteIndex

发生错误的字符索引.

xmlparser.ErrorCode

指定问题的数字代码。这个值可以传递到ErrorString()函数,或与中定义的常量之一进行比较errors宾语。

xmlparser.ErrorColumnNumber

发生错误的列号.

xmlparser.ErrorLineNumber

发生错误的行号.

以下属性包含与xmlparser宾语。在报告解析事件的回调期间,它们指示生成事件的第一个字符序列的位置。当在回调之外调用时,指示的位置将仅仅是最后一个解析事件(无论是否存在关联的回调).

xmlparser.CurrentByteIndex

解析器输入中的当前字节索引.

xmlparser.CurrentColumnNumber

解析器输入中的当前列号.

xmlparser.CurrentLineNumber

解析器输入中的当前行号.

以下是可以设置的处理程序列表。要在xmlparser对象o上设置处理程序,请使用o.handlername = func. handlername必须从以下列表中获取,并且func必须是一个可调用的对象,接受正确数量的参数。除非另有说明,否则论据都是字符串.

xmlparser.XmlDeclHandler (version, encoding, standalone )

解析XML声明时调用。XML声明是XML推荐的适用版本的(可选)声明,文档文本的编码,以及可选的“独立”声明.versionencoding将是字符串,如果声明文件是独立的,则standalone将是1,如果声明它不是独立的,则0,或-1如果省略了独立条款。这只适用于Expat版本1.95.0或更新版本.

xmlparser.StartDoctypeDeclHandlerdoctypeName, systemId, publicId, has_internal_subset)

当Expat开始解析文档类型声明(<!DOCTYPE...)时调用。doctypeName完全按照提供的方式提供。systemIdpublicId参数给出系统和公共标识符,如果指定,或None如果省略。has_internal_subset如果文档包含内部文档声明子集,则为true。这需要Expat version1.2或更新.

xmlparser.EndDoctypeDeclHandler ()

当Expat完成解析文档类型声明时调用。这需要Expat版本1.2或更新.

xmlparser.ElementDeclHandler (name, model)

为每个元素类型声明调用一次。name是元素类型的名称,而model是内容模型的表示.

xmlparser.AttlistDeclHandler (elname, attname, type, default, required)

元素类型的每个声明属性。如果属性listdeclaration声明了三个属性,则此处理程序被调用三次,每个属性一次。elname是声明适用的元素的名称,attname是声明的属性的名称。属性类型是一个传递为type的字符串;可能的值是"CDATA", "ID", "IDREF",… default给出文件实例未指定属性时使用的属性的默认值,或者None如果没有默认值(#IMPLIED值)。如果需要在文档实例中给出属性,则required将是真实的。这需要Expat版本1.95.0或更新.

xmlparser.StartElementHandler (name, attributes)

呼吁每个元素的开始。name是包含元素名称的字符串,attributes是元素属性。如果ordered_attributes为真,这是一个列表(见ordered_attributes完整的描述)。否则它是adictionary映射名称到值.

xmlparser.EndElementHandler (name)

在每个元素结束时调用.

xmlparser.ProcessingInstructionHandler (target, data

每次加工指令都要求.

xmlparser.CharacterDataHandler (data

调用字符数据。这将被称为普通字符数据,CDATAmarked内容和可忽略的空格。必须区分这些案件的应用可以使用StartCdataSectionHandler,EndCdataSectionHandlerElementDeclHandler回调tocollect所需信息.

xmlparser.UnparsedEntityDeclHandler (entityName, base, systemId, publicId, notationName )

调用未解析(NDATA)实体声明。这只是Expat库的版本1.2;对于更新的版本,使用EntityDeclHandler代替。(Expatlibrary中的基础函数已被宣布为过时。)

xmlparser.EntityDeclHandlerentityName, is_parameter_entity, value, base, systemId, publicId, notationName

为所有实体声明调用。对于参数和内部实体,value将是一个字符串,给出实体的声明内容;对外部实体来说,这将是NonenotationName参数对于已解析的实体将是None,对于unsarsedentities的表示法的名称。如果实体是一般实体的参数实体或false,则is_parameter_entity将为真(大多数应用程序仅需要关注一般实体)。这仅适用于从Explorer库的1.95.0版开始.

xmlparser.NotationDeclHandler (notationName, base, systemId, publicId)

用于表示声明。notationName, base,和systemId,和publicId如果给出的话就是字符串。如果省略公共标识符,publicId将是None.

xmlparser.StartNamespaceDeclHandlerprefix, uri

当元素包含名称空间声明时调用。名称空间声明在StartElementHandler为要声明的元素调用之前进行处理.

xmlparser.EndNamespaceDeclHandler (prefix )

在包含anamespace声明的元素到达结束标记时调用。这个元素的每个命名空间声明都调用一次,顺序与StartNamespaceDeclHandler被调用以指示每个名称空间声明的范围的开始。对这个处理程序的调用是在对应EndElementHandler之后对元素的结尾进行的.

xmlparser.CommentHandler (data

要求评论。data是评论的文字,不包括前导"<!--"和尾随"-->".

xmlparser.StartCdataSectionHandler

在一开始时调用CDATA部分。这和EndCdataSectionHandler需要能够识别CDATA部分的句法开始和结束.

xmlparser.EndCdataSectionHandler()

在CDATA部分的末尾打字.

xmlparser.DefaultHandlerdata

调用XML文档中没有指定任何适用处理程序的任何字符。这意味着属于可以报告的构造的一部分的字符,但是没有提供处理程序的字符.

xmlparser.DefaultHandlerExpanddata

这与DefaultHandler()相同,但不会抑制内部实体的扩展。实体引用不会传递给defaulthandler .

xmlparser.NotStandaloneHandler (

如果XML文档尚未被声明为独立文档,则调用。当存在外部子集或对参数的引用时会发生这种情况,但XML声明未单独设置为yes在XML声明中。如果此处理程序返回0,则解析器将引发XML_ERROR_NOT_STANDALONE错误。如果未设置此处理程序,解析器将针对此条件引发异常.

xmlparser.ExternalEntityRefHandler (context, base, systemId, publicId )

被调用以引用外​​部实体。base是当前的基数,由之前调用SetBase()设定。公共和系统标识符,systemIdpublicId,如果给出了字符串;如果没有公共标识符,publicId将是Nonecontext值是不透明的,应该如下所述使用.

对于要解析的外部实体,必须实现此处理程序。它负责使用ExternalEntityParserCreate(context),使用适当的回调初始化它,并解析实体。这个处理程序应返回一个整数;如果它回复0,解析器会举起XML_ERROR_EXTERNAL_ENTITY_HANDLING错误,否则解析将继续.

如果没有提供此处理程序,则DefaultHandler回调报告外部实体,如果提供的话

ExpatError异常

ExpatError异常有许多有趣的属性:

ExpatError.code

Expat的特定错误的内部错误号。errors.messages字典映射到Expat的错误消息的错误号。例如:

from xml.parsers.expat import ParserCreate, ExpatError, errorsp = ParserCreate()try:    p.Parse(some_xml_document)except ExpatError as err:    print("Error:", errors.messages[err.code])

errors模块还提供错误消息常量和字典codes将这些消息映射回错误代码,见下文.

ExpatError.lineno

检测到错误的行号。第一行编号为1.

ExpatError.offset

字符偏移到发生错误的行。第一列是编号0.

示例

下面的程序定义了三个只打印出来的处理程序.

import xml.parsers.expat# 3 handler functionsdef start_element(name, attrs):    print("Start element:", name, attrs)def end_element(name):    print("End element:", name)def char_data(data):    print("Character data:", repr(data))p = xml.parsers.expat.ParserCreate()p.StartElementHandler = start_elementp.EndElementHandler = end_elementp.CharacterDataHandler = char_datap.Parse("""<?xml version="1.0"?><parent id="top"><child1 name="paul">Text goes here</child1><child2 name="fred">More text</child2></parent>""", 1)

该程序的输出是:

Start element: parent {"id": "top"}Start element: child1 {"name": "paul"}Character data: "Text goes here"End element: child1Character data: "\n"Start element: child2 {"name": "fred"}Character data: "More text"End element: child2Character data: "\n"End element: parent

内容模型描述

使用嵌套元组描述内容模型。每个元组包含四个值:类型,量词,名称和子元组。Children只是附加的内容模型描述.

前两个字段的值是xml.parsers.expat.model模块中定义的常量。这些常量可以在两个组中收集:模型类型组和量词组.

模型类型组中的常量是:

xml.parsers.expat.model.XML_CTYPE_ANY

模型名称所指定的元素被声明为具有ANY.

xml.parsers.expat.model.XML_CTYPE_CHOICE

的内容模型命名元素允许从多个选项中进行选择;这用于内容模型,如(A | B | C).

xml.parsers.expat.model.XML_CTYPE_EMPTY

被声明为EMPTY的元素具有此模型类型.

xml.parsers.expat.model.XML_CTYPE_MIXED
xml.parsers.expat.model.XML_CTYPE_NAME
xml.parsers.expat.model.XML_CTYPE_SEQ

代表一系列模型的模型,这些模型一个接一个地表示使用此型号。这用于(A, B, C).

等模型。量词组中的常量是:

xml.parsers.expat.model.XML_CQUANT_NONE

没有给出修饰符,因此它可以恰好出现一次,如A.

xml.parsers.expat.model.XML_CQUANT_OPT

模型是可选的:它可以出现一次或者根本不出现,对于A?.

xml.parsers.expat.model.XML_CQUANT_PLUS

模型必须出现一次或多次(如A+).

xml.parsers.expat.model.XML_CQUANT_REP

模型必须出现零或多次,至于A*.

Expat错误常量

xml.parsers.expat.errors模块中提供了以下常量。这些常量在解释发生错误时引发的ExpatError异常对象的某些属性时非常有用。出于向后兼容性的原因,常量的值是错误message而不是数字错误code,你通过将code属性与errors.codes[errors.XML_ERROR_CONSTANT_NAME].

进行比较来实现这个errors模块具有以下属性:

xml.parsers.expat.errors.codes

字典映射数字错误代码到他们的字符串描述.

新版本3.2.

xml.parsers.expat.errors.messages

字典映射字符串描述到他们的错误代码.

新版本3.2.

xml.parsers.expat.errors.XML_ERROR_ASYNC_ENTITY
xml.parsers.expat.errors.XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF

属性值中的实体引用引用外部实体而不是内部实体.

xml.parsers.expat.errors.XML_ERROR_BAD_CHAR_REF

字符引用是指XML中非法的字符(例如,字符0或’&#0;‘).

xml.parsers.expat.errors.XML_ERROR_BINARY_ENTITY_REF

实体引用是指用符号声明的实体,不进行解析.

xml.parsers.expat.errors.XML_ERROR_DUPLICATE_ATTRIBUTE

在开始标记中多次使用了一个属性.

xml.parsers.expat.errors.XML_ERROR_INCORRECT_ENCODING
xml.parsers.expat.errors.XML_ERROR_INVALID_TOKEN

当输入字节无法正确分配给字符时引发;例如,UTF-8输入流中的NUL字节(值0).

xml.parsers.expat.errors.XML_ERROR_JUNK_AFTER_DOC_ELEMENT

在文档元素之后出现了除空白之外的东西.

xml.parsers.expat.errors.XML_ERROR_MISPLACED_XML_PI

在输入数据的开头以外的地方找到了XML声明.

xml.parsers.expat.errors.XML_ERROR_NO_ELEMENTS

该文档不包含任何元素(XML要求所有文档都包含一个顶级元素)..

xml.parsers.expat.errors.XML_ERROR_NO_MEMORY

Expat无法在内部分配内存.

xml.parsers.expat.errors.XML_ERROR_PARAM_ENTITY_REF

在不允许的地方找到参数实体引用.

xml.parsers.expat.errors.XML_ERROR_PARTIAL_CHAR

在输入中找到了不完整的字符.

xml.parsers.expat.errors.XML_ERROR_RECURSIVE_ENTITY_REF

实体引用包含对同一实体的另一个引用;可能是通过不同的名称,可能是间接的.

xml.parsers.expat.errors.XML_ERROR_SYNTAX

遇到了一些未指定的语法错误.

xml.parsers.expat.errors.XML_ERROR_TAG_MISMATCH

结束标记与最里面的开始标记不匹配.

xml.parsers.expat.errors.XML_ERROR_UNCLOSED_TOKEN

在流结束之前或者遇到下一个标记时,某些标记(例如开始标记)没有关闭.

xml.parsers.expat.errors.XML_ERROR_UNDEFINED_ENTITY

提到了一个没有定义的实体.

xml.parsers.expat.errors.XML_ERROR_UNKNOWN_ENCODING

Expat.不支持文档编码

xml.parsers.expat.errors.XML_ERROR_UNCLOSED_CDATA_SECTION

CDATA标记的部分未关闭.

xml.parsers.expat.errors.XML_ERROR_EXTERNAL_ENTITY_HANDLING
xml.parsers.expat.errors.XML_ERROR_NOT_STANDALONE

解析器确定文件不是“独立的”,虽然它声明自己在XML声明中,并且NotStandaloneHandler被设置并返回0.

xml.parsers.expat.errors.XML_ERROR_UNEXPECTED_STATE
xml.parsers.expat.errors.XML_ERROR_ENTITY_DECLARED_IN_PE
xml.parsers.expat.errors.XML_ERROR_FEATURE_REQUIRES_XML_DTD

请求了一个需要编译DTD支持的操作,但是在没有DTD支持的情况下配置了Expat。不应该通过xml.parsers.expat模块的标准构建来报告这个

xml.parsers.expat.errors.XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING

解析开始后请求行为更改,只有在解析开始之前才能更改。这(目前)仅由引发UseForeignDTD().

xml.parsers.expat.errors.XML_ERROR_UNBOUND_PREFIX

启用名称空间处理时找到未声明的前缀.

xml.parsers.expat.errors.XML_ERROR_UNDECLARING_PREFIX

文档试图删除与aprefix相关的名称空间声明.

xml.parsers.expat.errors.XML_ERROR_INCOMPLETE_PE

参数实体包含不完整的标记.

xml.parsers.expat.errors.XML_ERROR_XML_DECL

该文件根本没有文件内容.

xml.parsers.expat.errors.XML_ERROR_TEXT_DECL

解析外部实体中的文本声明时出错.

xml.parsers.expat.errors.XML_ERROR_PUBLICID

不允许在公共场所发现字符.

xml.parsers.expat.errors.XML_ERROR_SUSPENDED

请求的操作是在挂起的解析器上进行的,但是不允许。这包括尝试提供额外的输入或停止解析器.

xml.parsers.expat.errors.XML_ERROR_NOT_SUSPENDED

当解析器没有被挂起时,尝试恢复解析器.

xml.parsers.expat.errors.XML_ERROR_ABORTED

这不应该报告给Python应用程序.

xml.parsers.expat.errors.XML_ERROR_FINISHED

请求的操作是在完成解析输入的解析器上进行的,但是不允许。这包括尝试提供额外的输入或解析解析器.

xml.parsers.expat.errors.XML_ERROR_SUSPEND_PE

脚注

[1] XML输出中包含的编码字符串应符合适当的标准。例如,“UTF-8”有效,但“UTF8”不是。请参阅https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecland https://www.iana.org/assignments/character-sets/character-sets.xhtml.

评论被关闭。