xml.parsers.expat ---使用expat快速分析XML


警告

这个 pyexpat 模块对恶意构造的数据不安全。如果需要分析不可信或未经身份验证的数据,请参阅 XML漏洞 .

这个 xml.parsers.expat 模块是一个到expat非验证XML解析器的python接口。模块提供单一扩展类型, xmlparser ,表示XML分析器的当前状态。在一个 xmlparser 对象已创建,对象的各种属性可以设置为处理程序函数。当XML文档被送入解析器时,会为XML文档中的字符数据和标记调用处理程序函数。

此模块使用 pyexpat 提供对expat解析器的访问的模块。直接使用 pyexpat 模块已弃用。

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

exception xml.parsers.expat.ExpatError

expat报告错误时引发的异常。见节 expatError异常 有关解释expat错误的更多信息。

exception xml.parsers.expat.error

Alias ExpatError .

xml.parsers.expat.XMLParserType

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

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

xml.parsers.expat.ErrorString(errno)

返回给定错误号的解释字符串 埃尔诺 .

xml.parsers.expat.ParserCreate(encoding=None, namespace_separator=None)

创建并返回新的 xmlparser 对象。 encoding 如果指定,则必须是命名XML数据使用的编码的字符串。expat不支持像python那样多的编码,它的编码库不能扩展;它支持utf-8、utf-16、iso-8859-1(拉丁语1)和ascii。如果 encoding 1 它将重写文档的隐式或显式编码。

expat可以选择为您进行XML名称空间处理,通过提供 namespace_separator . 该值必须是一个字符串;a ValueError 如果字符串的长度非法,则将引发 (None 与省略相同)。启用命名空间处理时,将扩展属于命名空间的元素类型名称和属性名称。传递给元素处理程序的元素名称 StartElementHandlerEndElementHandler 将是名称空间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

由于 Expat 类库使用 pyexpat , the xmlparser 返回的实例只能用于分析单个XML文档。调用 ParserCreate 为每个文档提供唯一的解析器实例。

参见

The Expat XML Parser

expat项目的主页。

XmlParser对象

xmlparser 对象具有以下方法:

xmlparser.Parse(data[, isfinal])

分析字符串的内容 data ,调用相应的处理程序函数来处理已分析的数据。 是最后的 对该方法的最终调用必须为true;它允许以片段形式分析单个文件,而不是提交多个文件。 data 可以随时为空字符串。

xmlparser.ParseFile(file)

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

xmlparser.SetBase(base)

设置用于解析声明中系统标识符中相对URI的基。解析相对标识符留给应用程序:此值将作为 base 参数 ExternalEntityRefHandler()NotationDeclHandler()UnparsedEntityDeclHandler() 功能。

xmlparser.GetBase()

返回一个字符串,该字符串包含以前调用 SetBase()None 如果 SetBase() 还没调用。

xmlparser.GetInputContext()

以字符串形式返回生成当前事件的输入数据。数据是包含文本的实体的编码。当事件处理程序处于非活动状态时调用时,返回值为 None .

xmlparser.ExternalEntityParserCreate(context[, encoding])

创建一个“子”解析器,用于解析由父解析器解析的内容所引用的外部解析实体。这个 context 参数应为传递给 ExternalEntityRefHandler() 处理程序函数,如下所述。子解析器是用 ordered_attributesspecified_attributes 设置为此分析器的值。

xmlparser.SetParamEntityParsing(flag)

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

xmlparser.UseForeignDTD([flag])

用真值调用此 flag (默认)将导致expat调用 ExternalEntityRefHandler 具有 None 用于允许加载备用DTD的所有参数。如果文档不包含文档类型声明,则 ExternalEntityRefHandler 仍将被调用,但 StartDoctypeDeclHandlerEndDoctypeDeclHandler 不会被调用。

为传递错误值 flag 将取消以前传递真值的调用,否则无效。

此方法只能在 Parse()ParseFile() 方法;在调用其中一个方法之后调用它 ExpatError 将与 code 属性设置为 errors.codes[errors.XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING] .

xmlparser 对象具有以下属性:

xmlparser.buffer_size

buffer_text 是真的。可以通过为该属性分配新的整数值来设置新的缓冲区大小。当大小改变时,缓冲区将被刷新。

xmlparser.buffer_text

将此设置为真会导致 xmlparser 对象缓冲expat返回的文本内容,以避免对 CharacterDataHandler() 尽可能回拨。这可以大大提高性能,因为expat通常在每行结束时将字符数据分割成块。默认情况下,此属性为假,可以随时更改。

xmlparser.buffer_used

如果 buffer_text 启用时,缓冲区中存储的字节数。这些字节表示UTF-8编码文本。当 buffer_text 是假的。

xmlparser.ordered_attributes

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

xmlparser.specified_attributes

如果设置为非零整数,解析器将只报告那些在文档实例中指定的属性,而不是那些从属性声明派生的属性。设置此值的应用程序需要特别小心,以便根据需要使用声明中提供的附加信息,以符合XML处理器行为的标准。默认情况下,该属性为假;可以随时更改。

以下属性包含与 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 . 用户名 必须从以下列表中选取,并且 func 必须是接受正确数目参数的可调用对象。除非另有说明,否则参数都是字符串。

xmlparser.XmlDeclHandler(version, encoding, standalone)

在分析XML声明时调用。XML声明是XML建议的适用版本的声明(可选)、文档文本的编码以及可选的“独立”声明。 版本encoding 将是字符串,并且 独立的1 如果文档声明为独立的, 0 如果声明不独立,或 -1 如果省略了独立子句。此功能仅适用于1.95.0或更新版本的expat。

xmlparser.StartDoctypeDeclHandler(doctypeName, systemId, publicId, has_internal_subset)

当expat开始分析文档类型声明时调用 (<!DOCTYPE ... )这个 文档类型名 完全按照说明提供。这个 系统ID公共标识符 参数提供系统和公共标识符(如果指定),或者 None 如果省略。 has_internal_subset 如果文档包含内部文档声明子集,则为真。这需要expat版本1.2或更高版本。

xmlparser.EndDoctypeDeclHandler()

在expat分析完文档类型声明后调用。这需要expat版本1.2或更高版本。

xmlparser.ElementDeclHandler(name, model)

为每个元素类型声明调用一次。 name 是元素类型的名称,并且 模型 是内容模型的表示形式。

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

为元素类型的每个已声明属性调用。如果一个属性列表声明声明了三个属性,这个处理程序将被调用三次,每个属性一次。 名字 是应用声明的元素的名称,并且 收件人姓名 声明的属性的名称。属性类型是作为 type ;可能的值为 'CDATA''ID''IDREF' ,… default 为文档实例未指定属性时使用的属性提供默认值,或者 None 如果没有默认值 (#IMPLIED 价值观)。如果需要在文档实例中提供属性, 必修的 将会是真的。这需要expat版本1.95.0或更高版本。

xmlparser.StartElementHandler(name, attributes)

调用每个元素的开头。 name 是包含元素名称的字符串,并且 属性 是元素属性。如果 ordered_attributes 是的,这是一个列表(请参见 ordered_attributes 完整描述)。否则,它是一个将名称映射到值的字典。

xmlparser.EndElementHandler(name)

调用每个元素的结尾。

xmlparser.ProcessingInstructionHandler(target, data)

调用每个处理指令。

xmlparser.CharacterDataHandler(data)

调用字符数据。这将对普通字符数据、带CDATA标记的内容和可忽略的空白进行调用。必须区分这些情况的应用程序可以使用 StartCdataSectionHandlerEndCdataSectionHandlerElementDeclHandler 回拨以收集所需信息。

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

调用未分析的(数据)实体声明。这仅适用于expat库的1.2版;对于较新版本,请使用 EntityDeclHandler 相反。(expat库中的基础函数已被声明为已过时。)

xmlparser.EntityDeclHandler(entityName, is_parameter_entity, value, base, systemId, publicId, notationName)

调用所有实体声明。对于参数和内部实体, value 将是一个字符串,给出实体的声明内容;这将是 None 对于外部实体。这个 注释名 参数将为 None 对于已分析的实体,以及未分析实体的符号名称。 is_parameter_entity 如果实体是参数实体,则为真;对于一般实体,则为假(大多数应用程序只需要与一般实体相关)。这只能从1.95.0版的expat库开始提供。

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

调用了符号声明。 注释名base系统ID公共标识符 是字符串。如果省略了公共标识符, 公共标识符None .

xmlparser.StartNamespaceDeclHandler(prefix, uri)

当元素包含命名空间声明时调用。命名空间声明在 StartElementHandler 为放置声明的元素调用。

xmlparser.EndNamespaceDeclHandler(prefix)

当到达包含命名空间声明的元素的结束标记时调用。对元素上的每个命名空间声明调用一次,调用顺序与 StartNamespaceDeclHandler 调用以指示每个命名空间声明的作用域的开始。在相应的 EndElementHandler 元素的结尾。

xmlparser.CommentHandler(data)

征求意见。 data 是注释的文本,不包括前导 '<!- -' 尾随 '- ->' .

xmlparser.StartCdataSectionHandler()

在CDATA节的开头调用。这个和 EndCdataSectionHandler 需要能够识别CDATA部分的语法开始和结束。

xmlparser.EndCdataSectionHandler()

在CDATA节的末尾调用。

xmlparser.DefaultHandler(data)

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

xmlparser.DefaultHandlerExpand(data)

这和 DefaultHandler() 但不抑制内部实体的扩展。实体引用不会传递给默认处理程序。

xmlparser.NotStandaloneHandler()

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

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

调用对外部实体的引用。 base 是当前基,由上一个调用设置 SetBase() . 公共和系统标识符, 系统ID公共标识符 ,如果给定,则为字符串;如果未给定公共标识符, 公共标识符None . 这个 context 值是不透明的,只能按下面的说明使用。

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

如果未提供此处理程序,则外部实体由 DefaultHandler 回调(如果提供)。

expatError异常

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])

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

ExpatError.lineno

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

ExpatError.offset

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

例子

下面的程序定义了三个只打印出参数的处理程序。::

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

内容模型描述

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

前两个字段的值是在 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 发生错误时引发的异常对象。由于向后兼容的原因,常量的值是错误的 消息 而不是数字错误 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

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

xml.parsers.expat.errors.XML_ERROR_JUNK_AFTER_DOC_ELEMENT

在document元素后面出现了空白以外的内容。

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。