19.2. sgmllib — 简单的 SGML 解析器 — Python 文档
19.2. sgmllib — 简单的 SGML 解析器
自 2.6 版起已弃用:sgmllib 模块已在 Python 3 中删除。
该模块定义了一个类 SGMLParser,它作为解析 SGML(标准通用标记语言)格式的文本文件的基础。 事实上,它没有提供完整的 SGML 解析器——它只解析 HTML 使用的 SGML,并且该模块仅作为 htmllib 模块的基础存在。 HTMLParser 模块中提供了另一个支持 XHTML 并提供稍微不同界面的 HTML 解析器。
- class sgmllib.SGMLParser
- SGMLParser 类是在没有参数的情况下实例化的。 解析器被硬编码以识别以下结构:
- 分别为
<tag attr="value" ...>
和</tag>
形式的开始和结束标签。 &#name;
形式的数字字符引用。&name;
形式的实体引用。<!--text-->
形式的 SGML 注释。 请注意,在尾随的>
和紧接在前面的--
之间允许使用空格、制表符和换行符。
- 分别为
还定义了一个异常:
- exception sgmllib.SGMLParseError
SGMLParser 类在解析时遇到错误时引发的异常。
2.1 版中的新功能。
SGMLParser 实例有以下方法:
- SGMLParser.reset()
- 重置实例。 丢失所有未处理的数据。 这在实例化时隐式调用。
- SGMLParser.setnomoretags()
- 停止处理标签。 将所有后续输入视为文字输入 (CDATA)。 (这只是为了可以实现 HTML 标签
<PLAINTEXT>
。)
- SGMLParser.setliteral()
- 进入文字模式(CDATA 模式)。
- SGMLParser.feed(data)
- 向解析器提供一些文本。 它被处理,因为它由完整的元素组成; 不完整的数据将被缓冲,直到提供更多数据或 close() 被调用。
- SGMLParser.close()
- 强制处理所有缓冲数据,就好像它后面跟有文件结束标记一样。 该方法可能会被派生类重新定义,以在输入结束时定义额外的处理,但重新定义的版本应始终调用 close()。
- SGMLParser.get_starttag_text()
- 返回最近打开的开始标签的文本。 这通常不需要用于结构化处理,但在处理“已部署”的 HTML 或以最小的更改重新生成输入时可能很有用(可以保留属性之间的空白等)。
- SGMLParser.handle_starttag(tag, method, attributes)
调用此方法来处理已定义
start_tag()
或do_tag()
方法的开始标记。 tag 参数是转换为小写的标签名称, method 参数是用于支持开始标签语义解释的绑定方法。 attributes 参数是一个(name, value)
对的列表,其中包含在标签的<>
括号内找到的属性。name 已转换为小写。 value 中的双引号和反斜杠已被解释,以及已知字符引用和以分号终止的已知实体引用(通常,实体引用可以由任何非字母数字字符终止,但这会破坏
<A HREF="url?spam=1&eggs=2">
当eggs
是有效实体名称时的非常常见的情况)。例如,对于标签
<A HREF="http://www.cwi.nl/%22>
,该方法将被称为unknown_starttag('a', [('href', 'http://www.cwi.nl/')])
。 基本实现简单地调用 method,并使用 attributes 作为唯一参数。2.5 版新功能:处理属性值中的实体和字符引用。
- SGMLParser.handle_endtag(tag, method)
- 调用此方法来处理已为其定义
end_tag()
方法的结束标签。 tag 参数是转换为小写的标签名称, method 参数是应该用于支持结束标签语义解释的绑定方法。 如果没有为关闭元素定义end_tag()
方法,则不会调用此处理程序。 基本实现简单地调用 方法 。
- SGMLParser.handle_data(data)
- 调用此方法来处理任意数据。 它旨在被派生类覆盖; 基类实现什么都不做。
- SGMLParser.handle_charref(ref)
调用此方法来处理
&#ref;
形式的字符引用。 基本实现使用 convert_charref() 将引用转换为字符串。 如果该方法返回一个字符串,则将其传递给 handle_data(),否则调用unknown_charref(ref)
来处理错误。2.5 版更改: 使用 convert_charref() 而不是硬编码转换。
- SGMLParser.convert_charref(ref)
将字符引用转换为字符串,或
None
。 ref 是作为字符串传入的引用。 在基本实现中,ref 必须是 0-255 范围内的十进制数。 它转换使用 convert_codepoint() 方法找到的代码点。 如果 ref 无效或超出范围,则此方法返回None
。 此方法由默认 handle_charref() 实现和属性值解析器调用。2.5 版中的新功能。
- SGMLParser.convert_codepoint(codepoint)
将代码点转换为 str 值。 如果合适,可以在此处处理编码,尽管 sgmllib 的其余部分对此一无所知。
2.5 版中的新功能。
- SGMLParser.handle_entityref(ref)
调用此方法来处理形式为
&ref;
的通用实体引用,其中 ref 是通用实体引用。 它通过将 ref 传递给 convert_entityref() 来转换它。 如果返回一个翻译,它会调用带有翻译的方法 handle_data(); 否则,它调用方法unknown_entityref(ref)
。 默认entitydefs
定义了&
、'
、>
、<
和"
的翻译。2.5 版更改: 使用 convert_entityref() 而不是硬编码转换。
- SGMLParser.convert_entityref(ref)
将命名实体引用转换为 str 值或
None
。 结果值不会被解析。 ref 将只是实体的名称。 默认实现在实例(或类)变量entitydefs
中查找 ref,它应该是从实体名称到相应翻译的映射。 如果 ref 没有可用的翻译,则此方法返回None
。 此方法由默认 handle_entityref() 实现和属性值解析器调用。2.5 版中的新功能。
- SGMLParser.handle_comment(comment)
- 遇到注释时调用此方法。 comment 参数是一个字符串,包含
<!--
和-->
分隔符之间的文本,但不包含分隔符本身。 例如,注释<!--text-->
将导致使用参数'text'
调用此方法。 默认方法什么都不做。
- SGMLParser.handle_decl(data)
- 当解析器读取 SGML 声明时调用的方法。 实际上,
DOCTYPE
声明是 HTML 中唯一观察到的东西,但解析器不会区分不同(或损坏的)声明。 不支持DOCTYPE
声明中的内部子集。 data 参数将是<!
…>
标记内声明的全部内容。 默认实现什么都不做。
- SGMLParser.report_unbalanced(tag)
- 当找到不对应于任何打开元素的结束标记时调用此方法。
- SGMLParser.unknown_starttag(tag, attributes)
- 调用此方法来处理未知的开始标记。 它旨在被派生类覆盖; 基类实现什么都不做。
- SGMLParser.unknown_endtag(tag)
- 调用此方法来处理未知的结束标记。 它旨在被派生类覆盖; 基类实现什么都不做。
- SGMLParser.unknown_charref(ref)
- 调用此方法来处理无法解析的数字字符引用。 请参阅 handle_charref() 以确定默认处理的内容。 它旨在被派生类覆盖; 基类实现什么都不做。
- SGMLParser.unknown_entityref(ref)
- 调用此方法来处理未知实体引用。 它旨在被派生类覆盖; 基类实现什么都不做。
除了覆盖或扩展上面列出的方法外,派生类还可以定义以下形式的方法来定义特定标签的处理。 输入流中的标签名称与大小写无关; 方法名称中出现的 tag 必须小写:
- SGMLParser.start_tag(attributes)
- 调用该方法来处理开始标签标签。 它优先于
do_tag()
。 attributes 参数的含义与上述 handle_starttag() 的含义相同。
- SGMLParser.do_tag(attributes)
- 调用此方法来处理未定义
start_tag()
方法的开始标记 tag。 attributes 参数的含义与上述 handle_starttag() 的含义相同。
- SGMLParser.end_tag()
- 调用此方法来处理结束标记 tag。
请注意,解析器维护着一堆尚未找到结束标记的开放元素。 只有由 start_tag()
处理的标签才会被推送到这个堆栈上。 end_tag()
方法的定义对于这些标签是可选的。 对于do_tag()
或unknown_tag()
处理的标签,不需要定义end_tag()
方法; 如果定义,则不会使用。 如果标签的 start_tag()
和 do_tag()
方法都存在,则 start_tag()
方法优先。