19.2. sgmllib —简单的 SGML 解析器

自 2.6 版起弃用:sgmllib模块已在 Python 3 中删除。

该模块定义了一个SGMLParser类,该类用作解析以 SGML(标准通用标记语言)格式设置的文本文件的基础。实际上,它没有提供完整的 SGML 解析器-仅解析 HTML 所使用的 SGML,并且该模块仅作为htmllib模块的基础存在。 HTMLParser模块中提供了另一个支持 XHTML 并提供稍微不同的接口的 HTML 解析器。

  • 类别 sgmllib. SGMLParser

    • 实例SGMLParser类不带参数。解析器经过硬编码,可以识别以下结构:
  • 分别为<tag attr="value" ...></tag>形式的开始和结束标签。

  • 形式为&#name;的数字字符引用。

  • 形式为&name;的实体引用。

  • SGMLComments,格式为<!--text-->。请注意,在末尾的>和紧邻的--之间允许有空格,制表符和换行符。

还定义了一个 exception:

  • exception sgmllib. SGMLParseError
    • SGMLParser类在解析时遇到错误时引发的异常。

2.1 版中的新Function。

SGMLParser个实例具有以下方法:

  • SGMLParser. reset ( )

    • 重置实例。丢失所有未处理的数据。在实例化时隐式调用它。
  • SGMLParser. setnomoretags ( )

    • 停止处理标签。将所有后续 Importing 视为 LiteralsImporting(CDATA)。 (仅提供此标记是为了可以实现 HTML 标记<PLAINTEXT>.)
  • SGMLParser. setliteral ( )

    • 进入 Literals 模式(CDATA 模式)。
  • SGMLParser. feed(* data *)

    • 将一些文本 Importing 解析器。它是由完整元素组成的;缓冲不完整的数据,直到馈送更多数据或调用close()
  • SGMLParser. close ( )

    • 强制处理所有缓冲的数据,就好像其后面带有文件结束标记一样。派生类可以重新定义此方法,以在 Importing 末尾定义其他处理,但是重新定义的版本应始终调用close()
  • SGMLParser. get_starttag_text ( )

    • 返回最近打开的开始标签的文本。通常,结构化处理不需要此Function,但是在处理“已部署”的 HTML 或以最小的更改重新生成 Importing(可以保留属性之间的空白等)时可能很有用。
  • SGMLParser. handle_starttag(* tag method attributes *)

    • 调用此方法来处理已定义start_tag()do_tag()方法的开始标签。 * tag 参数是转换为小写字母的标签的名称,而 method *参数是绑定方法,应使用该方法来支持起始标签的语义解释。 * attributes *参数是(name, value)对的列表,其中包含在标签的<>括号内找到的属性。

名称已被翻译成小写。 * value *中的双引号和反斜杠以及已知的字符引用和已知的实体引用以分号终止(通常,实体引用可以由任何非字母数字字符终止)已得到解释,但这会 break 非常常见的情况当eggs是有效的实体名称时,则为<A HREF="url?spam=1&eggs=2">

例如,对于标签<A HREF="http://www.cwi.nl/">,此方法将称为unknown_starttag('a', [('href', 'http://www.cwi.nl/')])。基本实现只使用* attribute 作为唯一参数调用 method *。

2.5 版中的新Function:在属性值内处理实体和字符引用。

  • SGMLParser. handle_endtag(* tag method *)

    • 调用此方法来处理已定义end_tag()方法的结束标签。 * tag 参数是转换为小写字母的标签的名称,而 method 参数是绑定方法,应使用该方法来支持结束标签的语义解释。如果没有为结束元素定义end_tag()方法,则不会调用此处理程序。基本实现只是调用 method *。
  • SGMLParser. handle_data(* data *)

    • 调用此方法来处理任意数据。它旨在被派生类覆盖;Base Class 实现不执行任何操作。
  • 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 版的新Function。

  • SGMLParser. convert_codepoint(* codepoint *)
    • 将代码点转换为str值。适当的话也可以在这里处理编码,尽管sgmllib的其余部分在此问题上可以忽略。

2.5 版的新Function。

  • SGMLParser. handle_entityref(* ref *)
    • 调用此方法来处理格式为&ref;的通用实体引用,其中* ref 是通用实体引用。它pass将 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 ,该变量应为从实体名称到相应转换的 Map。如果 ref *没有可用的翻译,则此方法返回None。默认的handle_entityref()实现和属性值解析器调用此方法。

2.5 版的新Function。

  • SGMLParser. handle_comment(Comment)

    • 遇到 Comment 时调用此方法。 * comment *参数是一个字符串,其中包含<!---->分隔符之间的文本,但不包含分隔符本身。例如,Comments<!--text-->将导致使用参数'text'调用此方法。默认方法不执行任何操作。
  • SGMLParser. handle_decl(* data *)

    • 解析器读取 SGML 语句时调用的方法。实际上,DOCTYPE语句是在 HTML 中唯一观察到的内容,但是解析器不会区分不同的(或损坏的)语句。不支持DOCTYPE语句中的内部子集。 * data *参数将是<!>标记内语句的全部内容。默认实现不执行任何操作。
  • SGMLParser. report_unbalanced(* tag *)

    • 当找到与任何打开的元素都不对应的结束标记时,将调用此方法。
  • SGMLParser. unknown_starttag(* tag attributes *)

    • 调用此方法来处理未知的开始标记。它旨在被派生类覆盖;Base Class 实现不执行任何操作。
  • SGMLParser. unknown_endtag(* tag *)

    • 调用此方法来处理未知的结束标签。它旨在被派生类覆盖;Base Class 实现不执行任何操作。
  • SGMLParser. unknown_charref(* ref *)

    • 调用此方法来处理无法解析的数字字符引用。请参阅handle_charref(),以确定默认情况下要处理的内容。它旨在被派生类覆盖;Base Class 实现不执行任何操作。
  • SGMLParser. unknown_entityref(* ref *)

    • 调用此方法来处理未知实体引用。它旨在被派生类覆盖;Base Class 实现不执行任何操作。

除了覆盖或扩展上面列出的方法外,派生类还可以定义以下形式的方法来定义对特定标签的处理。Importing 流中的标签名称是大小写无关的。方法名称中出现的* tag *必须小写:

  • SGMLParser. start_tag(属性)

    • 调用此方法来处理开始标签* tag *。它优先于do_tag()。 * attribute *参数的含义与上述handle_starttag()相同。
  • SGMLParser. do_tag(属性)

    • 调用此方法来处理未定义start_tag()方法的开始标签* tag *。 * attribute *参数的含义与上述handle_starttag()相同。
  • SGMLParser. end_tag ( )

    • 调用此方法来处理结束标记* tag *。

请注意,解析器会维护一堆未找到结束标记的开放元素。仅由start_tag()处理的标签被压入该堆栈。对于这些标签,end_tag()方法的定义是可选的。对于由do_tag()unknown_tag()处理的标签,不需要定义end_tag()方法;如果定义,将不使用。如果标记同时存在start_tag()do_tag()方法,则start_tag()方法优先。