# 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="http://www.cwi.nl/">` を処理する場合、このメソッドは "`unknown_starttag('a', [('href', 'http://www.cwi.nl/')])`"として呼び出されます。基底クラスの実装では、単に method を単一の引数 attributes と共に呼び出します。

`handle_endtag`( | tag, method)

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

`handle_data`( | data)

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

`handle_charref`( | ref)

  このメソッドは "`&#ref;`" 形式の文字参照 (character reference) を処理するために呼び出されます。 基底クラスの実装では、ref は 0-255 の範囲の 10 進数で なければなりません。このメソッドは文字を ASCII に 変換し、 その文字を引数として `handle_data()` を 呼び出します。ref が無効な値か、範囲を超えた値である 場合、エラーを処理するために `unknown_charref(ref)` が呼び出されます。 名前づけされた文字エンティティをサポートするためには このメソッドをサブクラスで上書きしなければなりません。

`handle_entityref`( | ref)

  このメソッドは ref を一般エンティティ参照として、 "`&ref;`" 形式のエンティティ参照を処理するために 呼び出されます。

  このメソッドは、エンティティ名を対応する変換文字に対応付けている インスタンス (またはクラス) 変数である `entitydefs` 中で ref を探します。変換が見つかった場合、変換された文字を 引数にして `handle_data()` を呼び出します; そうでない場合、 `unknown_entityref(ref)` を呼び出します。 標準では `entitydefs` は `&amp;`、 `&apos`、 `&gt;`、 `&lt;`、および `&quot;` の変換を定義しています。

`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)

  このメソッドは対応する終了タグのない開始タグ 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()` が優先されます。