20.13. xml.parsers.expat
- 使用Expat 进行快速XML解析¶
警告
pyexpat
模块对于恶意构造的数据不安全。如果需要解析不受信任或未经身份验证的数据,请参阅XML vulnerabilities。
xml.parsers.expat
模块是Expat非验证XML解析器的Python接口。模块提供了一个单一的扩展类型,xmlparser
,它表示XML解析器的当前状态。在创建了xmlparser
对象后,可以将对象的各种属性设置为处理函数。当XML文档然后被馈送到解析器时,为XML文档中的字符数据和标记调用处理程序函数。
此模块使用pyexpat
模块提供对Expat解析器的访问。不推荐直接使用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.
ErrorString
(errno)¶ 返回给定错误号errno的说明字符串。
-
xml.parsers.expat.
ParserCreate
(encoding=None, namespace_separator=None)¶ 创建并返回一个新的
xmlparser
对象。encoding(如果指定)必须是用于命名XML数据所使用的编码的字符串。Expat不支持和Python一样多的编码,编码的编码不能扩展;它支持UTF-8,UTF-16,ISO-8859-1(Latin1)和ASCII。如果给定encoding [1],它将覆盖文档的隐式或显式编码。Expat可以为您选择执行XML命名空间处理,通过为namespace_separator提供值来启用。The value must be a one-character string; a
ValueError
will be raised if the string has an illegal length (None
is considered the same as omission). 启用命名空间处理时,将扩展属于命名空间的元素类型名称和属性名称。传递给元素处理程序StartElementHandler
和EndElementHandler
的元素名称将是命名空间URI,命名空间分隔符字符和名称的本地部分的连接。如果命名空间分隔符是一个零字节(chr(0)
),那么命名空间URI和本地部分将被连接而没有任何分隔符。例如,如果namespace_separator设置为空格字符(
' '
),并解析以下文档:<?xml version="1.0"?> <root xmlns = "http://default-namespace.org/" xmlns:py = "http://www.python.org/ns/"> <py:elem1 /> <elem2 xmlns="" /> </root>
StartElementHandler
将为每个元素接收以下字符串:http://default-namespace.org/ root http://www.python.org/ns/ elem1 elem2
由于
pyexpat
使用的Expat
库的限制,返回的xmlparser
实例只能用于解析单个XML文档。对每个文档调用ParserCreate
以提供唯一的解析器实例。
也可以看看
- Expat XML解析器
- Expat项目的主页。
20.13.1. XMLParser Objects¶
xmlparser
对象具有以下方法:
-
xmlparser.
Parse
(data[, isfinal])¶ 解析字符串data的内容,调用相应的处理函数来处理解析的数据。isfinal在最终调用此方法时必须为true;它允许在片段中解析单个文件,而不是提交多个文件。数据可以是任何时候的空字符串。
-
xmlparser.
ParseFile
(file)¶ 解析对象文件中的XML数据读取。文件只需提供
read(nbytes)
方法,当没有更多数据时返回空字符串。
-
xmlparser.
SetBase
(base)¶ 设置用于解析声明中系统标识符中的相对URI的基址。解析相对标识符留给应用程序:该值将作为
ExternalEntityRefHandler()
,NotationDeclHandler()
的基址和UnparsedEntityDeclHandler()
函数。
-
xmlparser.
GetInputContext
()¶ 以字符串形式返回生成当前事件的输入数据。数据在包含文本的实体的编码中。在事件处理程序未激活时调用时,返回值为
None
。
-
xmlparser.
ExternalEntityParserCreate
(context[, encoding])¶ 创建一个“子”解析器,可用于解析由父解析器解析的内容引用的外部解析实体。上下文参数应该是传递给
ExternalEntityRefHandler()
处理函数的字符串,如下所述。使用设置为此解析器的值的ordered_attributes
和specified_attributes
创建子解析器。
-
xmlparser.
SetParamEntityParsing
(flag)¶ 参数实体的控制解析(包括外部DTD子集)。可能的标志值为
XML_PARAM_ENTITY_PARSING_NEVER
,XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE
和XML_PARAM_ENTITY_PARSING_ALWAYS
。如果设置标志成功,则返回true。
-
xmlparser.
UseForeignDTD
([flag])¶ 使用标志(默认值)的真值调用此函数将导致Expat使用
None
为所有参数调用ExternalEntityRefHandler
,以允许备用DTD加载。如果文档不包含文档类型声明,则仍会调用ExternalEntityRefHandler
,但不会调用StartDoctypeDeclHandler
和EndDoctypeDeclHandler
。为标志传递false值将取消传递true值的以前调用,但其他方式没有效果。
This method can only be called before the
Parse()
orParseFile()
methods are called; calling it after either of those have been called causesExpatError
to be raised with thecode
attribute set toerrors.codes[errors.XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING]
.
xmlparser
对象具有以下属性:
-
xmlparser.
buffer_size
¶ buffer_text
为真时使用的缓冲区大小。可以通过为此属性分配一个新的整数值来设置新的缓冲区大小。当大小改变时,缓冲区将被刷新。
-
xmlparser.
buffer_text
¶ 将此设置为true会使
xmlparser
对象缓冲Expat返回的文本内容,以避免对可能的CharacterDataHandler()
回调的多次调用。这可以大大提高性能,因为Expat通常在每行结尾将字符数据分成块。默认情况下,此属性为false,并且可以随时更改。
-
xmlparser.
buffer_used
¶ 如果启用
buffer_text
,则存储在缓冲区中的字节数。这些字节表示UTF-8编码的文本。当buffer_text
为false时,此属性没有有意义的解释。
-
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推荐的适用版本的声明(可选),文档文本的编码以及可选的“独立”声明。version and encoding will be strings, and standalone will be
1
if the document is declared standalone,0
if it is declared not to be standalone, or-1
if the standalone clause was omitted. 这仅适用于Expat版本1.95.0或更高版本。
-
xmlparser.
StartDoctypeDeclHandler
(doctypeName, systemId, publicId, has_internal_subset)¶ Expat开始解析文档类型声明(
&lt;!DOCTYPE ...
)时调用。提供的doctypeName与提供的完全相同。systemId和publicId参数指定系统和公共标识符,如果省略,则None
。如果文档包含内部文档声明子集,则has_internal_subset将为true。这需要Expat版本1.2或更高版本。
-
xmlparser.
EndDoctypeDeclHandler
()¶ 当Expat完成解析文档类型声明时调用。这需要Expat版本1.2或更高版本。
-
xmlparser.
ElementDeclHandler
(name, model)¶ 每个元素类型声明调用一次。名称是元素类型的名称,模型是内容模型的表示。
-
xmlparser.
AttlistDeclHandler
(elname, attname, type, default, required)¶ 为元素类型的每个已声明的属性调用。如果一个属性列表声明声明了三个属性,这个处理程序被调用三次,每个属性一次。elname是声明应用的元素的名称,attname是声明的属性的名称。属性类型是作为类型传递的字符串;可能的值为
'CDATA'
,'ID'
,'IDREF'
,... 如果没有默认值(#IMPLIED
值),则在文档实例未指定属性时使用的属性默认值为None
。如果需要在文档实例中给出属性,则必需将为真。这需要Expat版本1.95.0或更高版本。
-
xmlparser.
StartElementHandler
(name, attributes)¶ 调用每个元素的开始。name是包含元素名称的字符串,属性是元素属性。如果
ordered_attributes
为true,则这是一个列表(有关完整说明,请参阅ordered_attributes
)。否则,它是一个字典将名称映射到值。
-
xmlparser.
EndElementHandler
(name)¶ 调用每个元素的结尾。
-
xmlparser.
ProcessingInstructionHandler
(target, data)¶ 调用每个处理指令。
-
xmlparser.
CharacterDataHandler
(data)¶ 调用字符数据。这将被称为正常字符数据,CDATA标记的内容和可忽略的空格。必须区分这些情况的应用程序可以使用
StartCdataSectionHandler
,EndCdataSectionHandler
和ElementDeclHandler
回调来收集所需的信息。
-
xmlparser.
UnparsedEntityDeclHandler
(entityName, base, systemId, publicId, notationName)¶ 调用已解析(NDATA)实体声明。这只存在于Expat库的1.2版本;对于更近的版本,请改用
EntityDeclHandler
。(Expat库中的基础函数已声明为过时。)
-
xmlparser.
EntityDeclHandler
(entityName, is_parameter_entity, value, base, systemId, publicId, notationName)¶ 调用所有实体声明。对于参数和内部实体,value将是一个给出实体声明内容的字符串;这将是外部实体的
None
。对于解析的实体,notationName参数将为None
,以及未解析实体的符号名称。如果实体是参数实体,则is_parameter_entity将为true,对于一般实体为false(大多数应用程序只需要关注一般实体)。这只能从Expat库的1.95.0版本开始提供。
-
xmlparser.
NotationDeclHandler
(notationName, base, systemId, publicId)¶ 调用符号声明。notationName,base和systemId和publicId都是字符串。如果省略公共标识符,publicId将为
None
。
-
xmlparser.
StartNamespaceDeclHandler
(prefix, uri)¶ 当元素包含命名空间声明时调用。在为放置声明的元素调用
StartElementHandler
之前处理命名空间声明。
-
xmlparser.
EndNamespaceDeclHandler
(prefix)¶ 当到达包含命名空间声明的元素的结束标记时调用。对于调用
StartNamespaceDeclHandler
的顺序的反向,对元素上的每个命名空间声明调用一次,以指示每个命名空间声明的作用域的开始。对此处理程序的调用在对应的EndElementHandler
之后作为元素的结尾。
-
xmlparser.
CommentHandler
(data)¶ 调用评论。data is the text of the comment, excluding the leading
'<!-
-'
and trailing'-
->'
.
-
xmlparser.
StartCdataSectionHandler
()¶ 在CDATA节开始时调用。需要这个和
EndCdataSectionHandler
,以便能够识别CDATA段的句法开始和结束。
-
xmlparser.
EndCdataSectionHandler
()¶ 在CDATA部分的末尾调用。
-
xmlparser.
DefaultHandler
(data)¶ 调用XML文档中未指定任何适用处理程序的任何字符。这意味着作为构造的一部分的字符可以被报告,但是没有提供处理程序。
-
xmlparser.
DefaultHandlerExpand
(data)¶ 这与
DefaultHandler()
相同,但不会抑制内部实体的扩展。实体引用不会传递给默认处理程序。
-
xmlparser.
NotStandaloneHandler
()¶ 如果XML文档尚未声明为独立文档,则调用此方法。当有一个外部子集或对一个参数实体的引用,但XML声明没有在XML声明中设置为独立到
yes
时,会发生这种情况。如果此处理程序返回0
,则解析器将引发一个XML_ERROR_NOT_STANDALONE
错误。如果未设置此处理程序,则此条件的解析器不会引发异常。
-
xmlparser.
ExternalEntityRefHandler
(context, base, systemId, publicId)¶ 调用对外部实体的引用。base是由先前调用
SetBase()
设置的当前基数。公共和系统标识符systemId和publicId是字符串,如果给定的话;如果未给出公共标识符,则publicId将为None
。上下文值是不透明的,并且应该仅按如下所述使用。对于要解析的外部实体,必须实现此处理程序。它负责使用
ExternalEntityParserCreate(context)
创建子解析器,使用适当的回调初始化它,并解析实体。这个处理程序应该返回一个整数;如果返回0
,解析器将引发一个XML_ERROR_EXTERNAL_ENTITY_HANDLING
错误,否则解析将继续。如果未提供此处理程序,则通过
DefaultHandler
回调(如果提供)报告外部实体。
20.13.2. ExpatError Exceptions¶
ExpatError
异常有一些有趣的属性:
-
ExpatError.
code
¶ Expat的特定错误的内部错误编号。
errors.messages
字典将这些错误号映射到Expat的错误消息。例如:from xml.parsers.expat import ParserCreate, ExpatError, errors p = ParserCreate() try: p.Parse(some_xml_document) except ExpatError as err: print("Error:", errors.messages[err.code])
-
ExpatError.
lineno
¶ 检测到错误的行号。第一行编号为
1
。
-
ExpatError.
offset
¶ 字符偏移到发生错误的行。第一列的编号为
0
。
20.13.3. Example¶
下面的程序定义了三个处理程序,只是打印出它们的参数。
import xml.parsers.expat
# 3 handler functions
def 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_element
p.EndElementHandler = end_element
p.CharacterDataHandler = char_data
p.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: child1
Character data: '\n'
Start element: child2 {'name': 'fred'}
Character data: 'More text'
End element: child2
Character data: '\n'
End element: parent
20.13.4. Content Model Descriptions¶
使用嵌套元组描述内容模型。每个元组包含四个值:类型,量词,名称和子元组。孩子只是额外的内容模型描述。
前两个字段的值是在xml.parsers.expat.model
模块中定义的常量。这些常量可以分为两组:模型类型组和量词组。
模型类型组中的常量为:
xml.parsers.expat.model。
XML_CTYPE_ANY
由模型名称命名的元素声明为具有
ANY
的内容模型。
xml.parsers.expat.model。
XML_CTYPE_CHOICE
命名的元素允许从多个选项中进行选择;这用于内容模型,例如
(A | B | C) / t5>
。
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*
。
20.13.5. Expat error constants¶
以下常量在xml.parsers.expat.errors
模块中提供。这些常量在解释发生错误时引发的ExpatError
异常对象的某些属性非常有用。由于向后兼容性原因,常量的值是错误消息而不是数字错误代码,您可以通过比较其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
或'�
')。
-
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
¶ 该文档试图删除与前缀相关联的名称空间声明。
-
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
¶ 在公共ID中找到不允许的字符。
-
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-EncodingDecl和https://www.iana.org/assignments/character- sets / character-sets.xhtml。 |