19.15. xml.parsers.expat —使用 Expat 的快速 XML 解析

Warning

pyexpat模块对于防止恶意构建的数据并不安全。如果您需要解析不可信或未经身份验证的数据,请参见XML vulnerabilities

2.0 版中的新Function。

xml.parsers.expat模块是 Expat 非验证 XML 解析器的 Python 接口。该模块提供了一个 extensionsxmlparser,它表示 XML 解析器的当前状态。创建xmlparser对象后,可以将对象的各种属性设置为处理函数。然后将 XML 文档 Importing 解析器时,将为 XML 文档中的字符数据和标记调用处理程序函数。

该模块使用pyexpat模块提供对 Expat 解析器的访问。不建议直接使用pyexpat模块。

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

  • exception xml.parsers.expat. ExpatError

    • Expat 报告错误时引发的异常。有关解释 Expat 错误的更多信息,请参见ExpatError Exceptions部分。
  • exception xml.parsers.expat. error

  • xml.parsers.expat. XMLParserType

xml.parsers.expat模块包含两个Function:

  • xml.parsers.expat. ErrorString(* errno *)

    • 返回给定错误号* errno *的说明性字符串。
  • xml.parsers.expat. ParserCreate([* encoding * [,* namespace_separator *]])

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

Expat 可以选择为您提供 XML 名称空间处理,方法是为* namespace_separator *提供一个值。该值必须是一个单字符字符串;如果字符串的长度非法(则将None视为与Ellipsis相同),则将引发ValueError。启用名称空间处理后,属于名称空间的元素类型名称和属性名称将被扩展。传递给元素处理程序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

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

See also

19.15.1. XMLParser 对象

xmlparser对象具有以下方法:

  • xmlparser. Parse(* data * [,* isfinal *])

    • 解析字符串* data 的内容,调用适当的处理函数以处理解析的数据。在此方法的finally调用中, isfinal *必须为 true;它允许以片段的形式解析单个文件,而不是多个文件的提交。 * data *可以随时为空字符串。
  • xmlparser. ParseFile(* file *)

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

  • xmlparser. GetBase ( )

    • 返回一个字符串,该字符串包含先前调用SetBase()None(如果尚未调用SetBase())而设置的基数。
  • xmlparser. GetInputContext ( )

    • 以字符串形式返回生成当前事件的 Importing 数据。数据采用包含文本的实体的编码。在事件处理程序不活动时调用时,返回值为None

2.1 版中的新Function。

  • xmlparser. ExternalEntityParserCreate(* context * [,* encoding *])

  • xmlparser. SetParamEntityParsing(* flag *)

    • 控制参数实体(包括外部 DTD 子集)的解析。可能的* flag *值为XML_PARAM_ENTITY_PARSING_NEVERXML_PARAM_ENTITY_PARSING_UNLESS_STANDALONEXML_PARAM_ENTITY_PARSING_ALWAYS。如果设置标志成功,则返回 true。
  • xmlparser. UseForeignDTD([* flag *])

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

该方法只能在调用Parse()ParseFile()方法之前调用;在调用其中任何一个之后调用它会导致ExpatErrorcode属性设置为errors.XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING的情况下引发。

2.3 版的新Function。

xmlparser个对象具有以下属性:

  • xmlparser. buffer_size
    • buffer_text为 true 时使用的缓冲区大小。可以pass为该属性分配新的整数值来设置新的缓冲区大小。更改大小后,缓冲区将被刷新。

2.3 版的新Function。

在 2.6 版中更改:现在可以更改缓冲区大小。

  • xmlparser. buffer_text
    • 将此属性设置为 true 会导致xmlparser对象缓冲 Expat 返回的文本内容,以避免在可能的情况下多次调用CharacterDataHandler()回调。由于 Expat 通常会在每行末尾将字符数据分成多个块,因此可以大大提高性能。默认情况下,此属性为 false,可以随时更改。

2.3 版的新Function。

  • xmlparser. buffer_used
    • 如果启用了buffer_text,则缓冲区中存储的字节数。这些字节代表 UTF-8 编码的文本。当buffer_text为 false 时,此属性没有有意义的解释。

2.3 版的新Function。

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

2.1 版中的新Function。

  • xmlparser. returns_unicode
    • 如果将此属性设置为非零整数,则处理函数将传递 Unicode 字符串。如果returns_unicodeFalse,则包含 UTF-8 编码数据的 8 位字符串将传递给处理程序。如果 Python 是使用 Unicode 支持构建的,则默认为True

在版本 1.6 中更改:可以随时更改以影响结果类型。

  • xmlparser. specified_attributes
    • 如果设置为非零整数,则解析器将仅报告在文档实例中指定的那些属性,而不报告从属性语句派生的那些属性。设置此设置的应用程序必须格外小心,以根据需要使用语句中提供的哪些附加信息,以符合 XML 处理器行为的标准。默认情况下,此属性为 false;否则为 false。它可以随时更改。

2.1 版中的新Function。

以下属性包含与xmlparser对象遇到的最新错误相关的值,并且仅在对Parse()ParseFile()的调用引发xml.parsers.expat.ExpatError异常后才具有正确的值。

  • xmlparser. ErrorByteIndex

    • 发生错误的字节索引。
  • xmlparser. ErrorCode

    • 指定问题的数字代码。该值可以传递给ErrorString()函数,或者与errors对象中定义的常量之一进行比较。
  • xmlparser. ErrorColumnNumber

    • 发生错误的列号。
  • xmlparser. ErrorLineNumber

    • 发生错误的行号。

以下属性包含与xmlparser对象中的当前解析位置有关的值。在报告解析事件的回调过程中,它们指示生成事件的字符序列中第一个字符的位置。在回调之外调用时,指示的位置将刚好在上一个解析事件之后(无论是否有关联的回调)。

2.4 版的新Function。

  • xmlparser. CurrentByteIndex

    • 解析器 Importing 中的当前字节索引。
  • xmlparser. CurrentColumnNumber

    • 解析器 Importing 中的当前列号。
  • xmlparser. CurrentLineNumber

    • 解析器 Importing 中的当前行号。

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

  • xmlparser. XmlDeclHandler(版本编码独立)
    • 解析 XML 语句时调用。 XML 语句是适用的 XML 建议版本的(可选)语句,文档文本的编码以及可选的“独立”语句。 * version encoding 将是returns_unicode属性所指定类型的字符串,如果文档被语句为独立文档,则 standalone *将为1;如果文档被语句为非独立文档,则为0;如果 standalone 子句是-1Ellipsis。仅适用于 Expat 1.95.0 或更高版本。

2.1 版中的新Function。

  • xmlparser. StartDoctypeDeclHandler(* doctypeName systemId publicId has_internal_subset *)

    • 当 Expat 开始解析文档类型语句(<!DOCTYPE ...)时调用。 * doctypeName 的提供与提供的完全相同。如果指定了 systemId publicId 参数,则提供系统和公共标识符;如果Ellipsis,则提供None。如果文档包含内部文档语句子集,则 has_internal_subset *将为 true。这需要 Expat 1.2 版或更高版本。
  • xmlparser. EndDoctypeDeclHandler ( )

    • 当 Expat 完成文档类型语句的解析时调用。这需要 Expat 1.2 版或更高版本。
  • xmlparser. ElementDeclHandler(* name model *)

    • 为每个元素类型语句调用一次。 * name 是元素类型的名称,而 model *是内容模型的表示。
  • xmlparser. AttlistDeclHandler(* elname attname type default required *)

    • 为元素类型的每个语句的属性调用。如果属性列表语句语句了三个属性,则此处理程序将被调用三次,每个属性一次。 * elname 是语句适用的元素的名称, attname 是语句的属性的名称。属性类型是作为 type 传递的字符串;可能的值为'CDATA''ID''IDREF',… default 给出当文档实例未指定属性时使用的属性的默认值;如果没有默认值(#IMPLIED值),则为None。如果要求在文档实例中提供该属性,则 required *为 true。这需要 Expat 1.95.0 或更高版本。
  • xmlparser. StartElementHandler(* name attributes *)

    • 要求每个元素的开始。 * name 是包含元素名称的字符串,而 attributes *是将属性名称 Map 为其值的字典。
  • xmlparser. EndElementHandler(* name *)

    • 要求每个元素的结尾。
  • xmlparser. ProcessingInstructionHandler(* target data *)

    • 调用每个处理指令。
  • xmlparser. CharacterDataHandler(* data *)

  • xmlparser. UnparsedEntityDeclHandler(* entityName base systemId publicId notationName *)

    • 调用未解析的(NDATA)实体语句。仅适用于 Expat 库的 1.2 版。要获取最新版本,请改用EntityDeclHandler。 (Expat 库中的基础Function已被宣布作废.)
  • xmlparser. EntityDeclHandler(* entityName is_parameter_entity value base systemId publicId notationName *)

    • 要求所有实体语句。对于参数和内部实体,* value 将是给出实体语句内容的字符串;对于外部实体,这将是None。对于已解析的实体, notationName 参数将为None,对于未解析的实体,参数的名称将为。如果实体是参数实体,则 is_parameter_entity 将为 true;对于一般实体, is_parameter_entity *将为 false(大多数应用程序只需要与一般实体有关)。仅从 Expat 库的 1.95.0 版开始可用。

2.1 版中的新Function。

  • xmlparser. NotationDeclHandler(* notationName base systemId publicId *)

    • 要求符号语句。 * notationName base systemId 以及 publicId 是字符串(如果提供)。如果Ellipsis公共标识符,则 publicId *将为None
  • xmlparser. StartNamespaceDeclHandler(前缀,* uri *)

    • 当元素包含名称空间语句时调用。命名空间语句在放置语句的元素被调用StartElementHandler之前被处理。
  • xmlparser. EndNamespaceDeclHandler(前缀)

    • 当包含命名空间语句的元素到达结束标记时调用。对于元素上的每个命名空间语句,将以与调用StartNamespaceDeclHandler的 Sequences 相反的 Sequences 调用一次,以指示每个命名空间语句的范围的开始。在元素末尾的相应EndElementHandler之后调用此处理程序。
  • xmlparser. CommentHandler(* data *)

    • 征求意见。 * data *是 Comments 的文本,不包括开头的'<!- -'和结尾的'- ->'
  • xmlparser. StartCdataSectionHandler ( )

    • 在 CDATA 节的开头调用。需要此和EndCdataSectionHandler才能识别 CDATA 节的句法起点和 endpoints。
  • 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。 * context *值是不透明的,仅应按以下说明使用。

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

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

19.15.2. ExpatError 异常

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

  • ExpatError. code
    • 针对特定错误的 Expat 内部错误号。这将与该模块中errors对象中定义的常量之一匹配。

2.1 版中的新Function。

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

2.1 版中的新Function。

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

2.1 版中的新Function。

19.15.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

19.15.4. 内容模型说明

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

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

模型类型组中的常量为:

  • xml.parsers.expat. XML_CTYPE_ANY

    • 语句了由模型名称命名的元素的内容模型为ANY
  • xml.parsers.expat. XML_CTYPE_CHOICE

    • named 元素允许从多个选项中进行选择。用于诸如(A | B | C)之类的内容模型。
  • xml.parsers.expat. XML_CTYPE_EMPTY

    • 语句为EMPTY的元素具有此模型类型。
  • xml.parsers.expat. XML_CTYPE_MIXED

  • xml.parsers.expat. XML_CTYPE_NAME

  • xml.parsers.expat. XML_CTYPE_SEQ

    • 用这种模型类型表示代表一系列彼此接连的模型的模型。用于(A, B, C)之类的模型。

量词组中的常量为:

  • xml.parsers.expat. XML_CQUANT_NONE

    • 没有给出修饰符,因此它只能出现一次,就像A一样。
  • xml.parsers.expat. XML_CQUANT_OPT

    • 该模型是可选的:就A?而言,它可以显示一次或完全不显示。
  • xml.parsers.expat. XML_CQUANT_PLUS

    • 该模型必须发生一次或多次(如A+)。
  • xml.parsers.expat. XML_CQUANT_REP

    • A*一样,该模型必须出现 0 次或多次。

19.15.5. 扩展错误常量

xml.parsers.expat模块的errors对象中提供了以下常量。这些常量在解释发生错误时引发的ExpatError异常对象的某些属性时很有用。

errors对象具有以下属性:

  • xml.parsers.expat. XML_ERROR_ASYNC_ENTITY

  • xml.parsers.expat. XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF

    • 属性值中的实体引用是指外部实体而不是内部实体。
  • xml.parsers.expat. XML_ERROR_BAD_CHAR_REF

    • 字符引用引用了 XML 中非法的字符(例如,字符0或'&#0;')。
  • xml.parsers.expat. XML_ERROR_BINARY_ENTITY_REF

    • 实体引用是指已使用符号语句的实体,因此无法解析。
  • xml.parsers.expat. XML_ERROR_DUPLICATE_ATTRIBUTE

    • 在开始标记中多次使用一个属性。
  • xml.parsers.expat. XML_ERROR_INCORRECT_ENCODING

  • xml.parsers.expat. XML_ERROR_INVALID_TOKEN

    • 在无法将 Importing 字节正确分配给字符时引发;例如,UTF-8Importing 流中的 NUL 字节(值0)。
  • xml.parsers.expat. XML_ERROR_JUNK_AFTER_DOC_ELEMENT

    • 在文档元素之后出现了除空格以外的其他内容。
  • xml.parsers.expat. XML_ERROR_MISPLACED_XML_PI

    • 在 Importing 数据的开头以外的地方找到了 XML 语句。
  • xml.parsers.expat. XML_ERROR_NO_ELEMENTS

    • 该文档不包含任何元素(XML 要求所有文档仅包含一个顶级元素)。
  • xml.parsers.expat. XML_ERROR_NO_MEMORY

    • Expat 无法在内部分配内存。
  • xml.parsers.expat. XML_ERROR_PARAM_ENTITY_REF

    • 在不允许的地方找到了参数实体引用。
  • xml.parsers.expat. XML_ERROR_PARTIAL_CHAR

    • 在 Importing 中发现不完整的字符。
  • xml.parsers.expat. XML_ERROR_RECURSIVE_ENTITY_REF

    • 实体引用包含对同一实体的另一个引用;可能使用其他名称,也可能间接使用。
  • xml.parsers.expat. XML_ERROR_SYNTAX

    • 遇到一些未指定的语法错误。
  • xml.parsers.expat. XML_ERROR_TAG_MISMATCH

    • 结束标签与最里面的开始标签不匹配。
  • xml.parsers.expat. XML_ERROR_UNCLOSED_TOKEN

    • 在流结束或遇到下一个标记之前,未关闭某些标记(例如开始标记)。
  • xml.parsers.expat. XML_ERROR_UNDEFINED_ENTITY

    • 引用了一个未定义的实体。
  • xml.parsers.expat. XML_ERROR_UNKNOWN_ENCODING

    • Expat 不支持文档编码。
  • xml.parsers.expat. XML_ERROR_UNCLOSED_CDATA_SECTION

    • CDATA 标记的部分未关闭。
  • xml.parsers.expat. XML_ERROR_EXTERNAL_ENTITY_HANDLING

  • xml.parsers.expat. XML_ERROR_NOT_STANDALONE

    • 解析器确定该文档虽然语句自己位于 XML 语句中,但它不是“独立的”,并且设置了NotStandaloneHandler并返回0
  • xml.parsers.expat. XML_ERROR_UNEXPECTED_STATE

  • xml.parsers.expat. XML_ERROR_ENTITY_DECLARED_IN_PE

  • xml.parsers.expat. XML_ERROR_FEATURE_REQUIRES_XML_DTD

    • 请求了需要编译 DTD 支持的操作,但是 Expat 配置为没有 DTD 支持。 xml.parsers.expat模块的标准内部版本绝对不应报告此情况。
  • xml.parsers.expat. XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING

    • 解析开始后要求进行行为更改,该行为只能在解析开始之前进行更改。 (当前)仅由UseForeignDTD()引发。
  • xml.parsers.expat. XML_ERROR_UNBOUND_PREFIX

    • 启用名称空间处理时,发现未语句的前缀。
  • xml.parsers.expat. XML_ERROR_UNDECLARING_PREFIX

    • 该文档try删除与前缀关联的名称空间语句。
  • xml.parsers.expat. XML_ERROR_INCOMPLETE_PE

    • 参数实体包含不完整的标记。
  • xml.parsers.expat. XML_ERROR_XML_DECL

    • 该文档完全没有文档元素。
  • xml.parsers.expat. XML_ERROR_TEXT_DECL

    • 解析外部实体中的文本语句时出错。
  • xml.parsers.expat. XML_ERROR_PUBLICID

    • 在公共 ID 中找到了不允许的字符。
  • xml.parsers.expat. XML_ERROR_SUSPENDED

    • 所请求的操作是在暂停的解析器上进行的,但不允许执行。这包括try提供其他 Importing 或停止解析器。
  • xml.parsers.expat. XML_ERROR_NOT_SUSPENDED

    • 尚未暂停解析器时,try恢复解析器。
  • xml.parsers.expat. XML_ERROR_ABORTED

    • 这不应报告给 Python 应用程序。
  • xml.parsers.expat. XML_ERROR_FINISHED

    • 所请求的操作是在解析器上进行的,解析器已完成对 Importing 的解析,但不允许这样做。这包括try提供其他 Importing 或停止解析器。
  • xml.parsers.expat. XML_ERROR_SUSPEND_PE

Footnotes