19.2. sgmllib — 简单的 SGML 解析器 — Python 文档

来自菜鸟教程
Python/docs/2.7/library/sgmllib
跳转至:导航、​搜索

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)

将字符引用转换为字符串,或 Noneref 是作为字符串传入的引用。 在基本实现中,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 定义了 &amp;&apos;&gt;&lt;&quot; 的翻译。

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() 方法的开始标记 tagattributes 参数的含义与上述 handle_starttag() 的含义相同。
SGMLParser.end_tag()
调用此方法来处理结束标记 tag

请注意,解析器维护着一堆尚未找到结束标记的开放元素。 只有由 start_tag() 处理的标签才会被推送到这个堆栈上。 end_tag() 方法的定义对于这些标签是可选的。 对于do_tag()unknown_tag()处理的标签,不需要定义end_tag()方法; 如果定义,则不会使用。 如果标签的 start_tag()do_tag() 方法都存在,则 start_tag() 方法优先。