# 2 `sgmllib` -- 単純な SGML パーザ

このモジュールでは SGML (Standard Generalized Mark-up Language: 汎用マークアップ言語標準) で書式化されたテキストファイルを解析 するための基礎として働く `SGMLParser` クラスを定義しています。 実際には、このクラスは完全な SGML パーザを提供しているわけではありません -- このクラスは HTML で用いられているような SGML だけを解析し、 モジュール自体も `htmllib` モジュールの基礎にするため だけに存在しています。XHTML をサポートし、少し異なったインタフェースを 提供しているもう一つの HTML パーザは、`HTMLParser` モジュールで使うことができます。

クラス `SGMLParser`( | )

  `SGMLParser` クラスは引数無しでインスタンス化されます。 このパーザは以下の構成を認識するようにハードコードされています:

  - "`<tag attr="value" ...>`" と "`</tag>`" で表されるタグの開始部と終了部。

  - "`&#name;`" 形式をとる文字の数値参照。

  - "`&name;`" 形式をとるエンティティ参照。

  - "`<!--text-->`" 形式をとる SGML コメント。 末尾の "`>`" とその直前にある "`--`" の間には スペース、タブ、改行を入れることができます。

例外が以下のように定義されます:

exception `SGMLParseError`
  `SGMLParser`クラスで構文解析中にエラーに出逢うとこの例外が発生します。 バージョン 2.1 で 新たに追加 された仕様です。

`SGMLParser` インスタンスは以下のメソッドを持っています:

`reset`( | )

  インスタンスをリセットします。未処理のデータは全て失われます。 このメソッドはインスタンス生成時に非明示的に呼び出されます。

`setnomoretags`( | )

  タグの処理を停止します。以降の入力をリテラル入力 (CDATA) として扱います。(この機能は HTML タグ `<PAINTEXT>` を実装 できるようにするためだけに提供されています)

`setliteral`( | )

  リテラルモード (CDATA モード) に移行します。

`feed`( | data)

  テキストをパーザに入力します。入力は完全なエレメントから成り立つ 場合に限り処理されます; 不完全なデータは追加のデータが入力されるか、 `close()` が呼び出されるまでバッファに蓄積されます。

`close`( | )

  バッファに蓄積されている全てのデータについて、直後にファイル終了記号 が来た時のようにして強制的に処理します。このメソッドは導出クラスで 再定義して、入力の終了時に追加の処理行うよう定義することができますが、 このメソッドの再定義されたバージョンでは常に `close()` を呼び出さなければなりません。

`get_starttag_text`( | )

  もっとも最近開かれた開始タグのテキストを返します。通常、構造化された データの処理をする上でこのメソッドは必要ありませんが、 ``広く知られている (as deployed)'' HTML を扱ったり、入力を 最小限の変更で再生成 (属性間の空白をそのままにする、など) したり する場合に便利なことがあります。

`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/">` を処理する場合、このメソッドは "`unknown_starttag('a', [('href', 'http://www.cwi.nl/')])`"として呼び出されます。基底クラスの実装では、単に method を単一の引数 attributes と共に呼び出します。 バージョン 2.5 で 新たに追加 された仕様: 属性値中のエンティティおよび文字参照の扱い

`handle_endtag`( | tag, method)

  このメソッドは `end_tag()` メソッドの定義されている 終了タグを処理するために呼び出されます。 tag 引数はタグの名前で、小文字に変換されており、 method 引数は終了タグの意味解釈をサポートするために使われる バインドされたメソッドです。`end_tag()` メソッドが 終了エレメントとして定義されていない場合、ハンドラは一切呼び出され ません。基底クラスの実装では単に method を呼び出します。

`handle_data`( | data)

  このメソッドは何らかのデータを処理するために呼び出されます。 導出クラスで上書きするためのメソッドです; 基底クラスの実装では 何も行いません。

`handle_charref`( | ref)

  このメソッドは "`&#ref;`" 形式の文字参照 (character reference) を処理するために呼び出されます。 基底クラスの実装は、`convert_charref()` を使って 参照を文字列に変換します。 もしそのメソッドが文字列を返せば `handle_data()` を 呼び出します。そうでなければ、 エラーを処理するために `unknown_charref(ref)` が呼び出されます。 バージョン 2.5 で 変更 された仕様: ハードコードされた変換に代わり `convert_charref()` を使います

`convert_charref`( | ref)

  文字参照を文字列に変換するか、`None` を返します。 ref は文字列として渡される参照です。基底クラスでは ref は 0-255 の範囲の十進数でなければなりません。 そしてコードポイントをメソッド `convert_codepoint()` を使って変換します。もし ref が不正もしくは範囲外ならば、 `None` を返します。このメソッドはデフォルト実装の `handle_charref` から、あるいは属性値パーザから呼び出されます。 バージョン 2.5 で 新たに追加 された仕様です。

`convert_codepoint`( | codepoint)

  コードポイントを `str` の値に変換します。もしそれが適切ならば エンコーディングをここで扱うこともできますが、`sgmllib` の 残りの部分はこの問題に関知しません。 バージョン 2.5 で 新たに追加 された仕様です。

`handle_entityref`( | ref)

  このメソッドは ref を一般エンティティ参照として、 "`&ref;`" 形式のエンティティ参照を処理するために 呼び出されます。 このメソッドは、ref を `convert_entityref()` に渡して 変換します。変換結果が返された場合、変換された文字を 引数にして `handle_data()` を呼び出します; そうでない場合、 `unknown_entityref(ref)` を呼び出します。 標準では `entitydefs` は `&amp;`、 `&apos`、 `&gt;`、 `&lt;`、および `&quot;` の変換を定義しています。 バージョン 2.5 で 変更 された仕様: ハードコードされた変換に代わり `convert_entityref()` を使います

`convert_entityref`( | ref)

  名前付きエンティティ参照を `str` の値に変換するか、または `None` を返します。変換結果は再パーズしません。 ref はエンティティの名前部分だけ です。デフォルトの実装ではインスタンス(またはクラス)変数の `entitydefs` というエンティティ名から対応する文字列へのマッピング から ref を探します。もし ref に対応する文字列が見つからなければ メソッドは `None` を返します。このメソッドは `handle_entityref()` のデフォルト実装からおよび属性値パーザから呼び出されます。 バージョン 2.5 で 新たに追加 された仕様です。

`handle_comment`( | comment)

  このメソッドはコメントに遭遇した場合に呼び出されます。comment 引数は文字列で、"`<!--`" and "`-->`" デリミタ間の、 デリミタ自体を除いたテキストが収められています。例えば、コメント "`<!--text-->`" があると、このメソッドは引数 `'text'` で呼び出されます。基底クラスの実装では何も行いません。

`handle_decl`( | data)

  パーザが SGML 宣言を読み出した際に呼び出されるメソッドです。 実際には、`DOCTYPE` は HTML だけに見られる宣言ですが、 パーザは宣言間の相違 (や誤った宣言) を判別しません。`DOCTYPE` の内部サブセット宣言はサポートされていません。 decl パラメタは `<!`...`>` 記述内の宣言内容 全体になります。基底クラスの実装では何も行いません。

`report_unbalanced`( | tag)

  個のメソッドは対応する開始エレメントのない終了タグが発見された 時に呼び出されます。

`unknown_starttag`( | tag, attributes)

  未知の開始タグを処理するために呼び出されるメソッドです。 導出クラスで上書きするためのメソッドです; 基底クラスの実装では 何も行いません。

`unknown_endtag`( | tag)

  This method is called to process an unknown end tag. 未知の終了タグを処理するために呼び出されるメソッドです。 導出クラスで上書きするためのメソッドです; 基底クラスの実装では 何も行いません。

`unknown_charref`( | ref)

  このメソッドは解決不能な文字参照数値を処理するために呼び出され ます。標準で何が処理可能かは `handle_charref()` を参照 してください。 導出クラスで上書きするためのメソッドです; 基底クラスの実装では 何も行いません。

`unknown_entityref`( | ref)

  未知のエンティティ参照を処理するために呼び出されるメソッドです。 導出クラスで上書きするためのメソッドです; 基底クラスの実装では 何も行いません。

上に挙げたメソッドを上書きしたり拡張したりするのとは別に、導出 クラスでは以下の形式のメソッドを定義して、特定のタグを処理する こともできます。入力ストリーム中のタグ名は大小文字の区別に依存 しません; メソッド名中の tag は小文字でなければなりません:

start_tag( | attributes)

  このメソッドは開始タグ tag を処理するために呼び出されます。 `do_tag()` よりも高い優先順位があります。 attributes 引数は上の `handle_starttag()` で記述されて いるのと同じ意味です。

do_tag( | attributes)

  このメソッドは `start_tag` メソッドが定義されていない 開始タグ tag を処理するために呼び出されます。 attributes 引数は上の `handle_starttag()` で記述されて いるのと同じ意味です。

end_tag( | )

  このメソッドは終了タグ tag を処理するために呼び出されます。

パーザは開始されたエレメントのうち、終了タグがまだ見つかっていない もののスタックを維持しているので注意してください。 `start_tag()` で処理されたタグだけがスタックにプッシュ されます。are pushed on this stack. Definition of an それらのタグに対する `end_tag()` メソッドの定義は オプションです。`do_tag()` や `unknown_tag()` で処理されるタグについては、`end_tag()` を定義しては いけません; 定義されていても使われることはありません。 あるタグに対して `start_tag` および `do_tag()` メソッドの両方が存在する場合、`start_tag()` が優先されます。