sxml.ssax
- 関数的なXMLパーザ ¶sxml.*
モジュールは、XML構造のS式表現に基づく
Oleg KiselyovのSXMLフレームワーク(http://okmij.org/ftp/Scheme/xml.html)の適合です。
SSAXは、SXMLフレームワークのパーザ部分です。以下は、 SSAXのウェブページからの引用です。
SSAXは関数的なXMLパージングフレームワークで、DOM/SXMLパーザ、SAXパーザ、 字句解析・構文解析手続きのサポートライブラリから構成されます。 パッケージ内の手続きは、XML文書の様々な部分をトークナイズ、あるいは パーズするために独立して使うことができます。 このフレームワークは、XML名前空間、文字、内部および外部解析済み実体、 属性値の正規化、処理命令とCDATAセクションをサポートしています。 パッケージは、ある程度の妥当性検査を行うSXMLパーザ: SAXパーザの インスタンスであるDOMモードのパーザ(SSAXと呼ばれます)を含んでいます。
現在のバージョンは、SXMLツールセットの最新の’公式な’リリース(4.9)よりも
新しい、SSAXのCVSバージョンをベースにしており、パッケージSXML-gauche-0.9は、
SXML-4.9をベースにしています。
SXMLのリリース4.9以降では、重要な変更があります。
現在のAPIでは、大文字の接頭辞SSAX:
の代わりに小文字のssax:
を
使います。Gaucheはデフォルトで文字の大小を区別するために、この違いは
問題となります。
後方互換性のためにエイリアスされた名前が定義されていますが、
大文字の接頭辞付きの名前の使用は推奨されません。
マニュアルのこのパートの内容はSSAXのソースコードから抽出されたもので、 単にそのコメントをTexinfoのフォーマットに変換しただけです。 オリジナルのテキストは、Oleg Kiselyovによるものです。 変換により生じた誤字・誤植やフォーマットエラーの責任は、 Shiro Kawaiにあります。
このマニュアルのエントリは、低レベルの構造から高レベルのユーティリティへと
“ボトムアップ”の方法で並べられています。
もし、あなたが単にXMLドキュメントをパーズしたりSXMLを得たいだけならば、
SSAXの高レベルのパーザ - XMLからSXMLへのssax:xml->sxml
を
チェックして下さい。
• SSAXデータタイプ: | ||
• SSAXの低レベルパージングコード: | ||
• SSAXの高レベルのパーザとスキャナ: | ||
• SSAXの高レベルのパーザ - XMLからSXMLへ: |
シンボル’START
、’END
、’PI
、’DECL
、’COMMENT
、
’CDSECT
は、マークアップトークンを識別するものです。
XML文書で、マークアップトークン: 開始タグ、PI
ターゲット、属性名に
与えられる名前(XML勧告ではGI
と呼ばれます)です。
GI
がNCName
である場合、UNRES-NAMEはこのNCName
が
Schemeのシンボルに変換されたものになります。
GI
がQName
ならば、UNRES-NAMEは、シンボルのペア、
(PREFIX . LOCALPART)となります。
展開された名前、つまりUNRES-NAMEの解決されたバージョンです。 名前空間URIが空でない場合の要素や属性名では、RES-NAMEはシンボルのペア、 (URI-SYMB . LOCALPART)です。そうでない場合は、1つのシンボルです。
以下のシンボルのうちの1つです。
ANY | 何でもよく、ENDタグがあるもの。 |
EMPTY-TAG | 内容がなく、ENDタグのないもの。 |
EMPTY | 内容がなく、次のトークンがENDタグであるもの。 |
PCDATA | 文字データのみで、子要素がないもの。 |
MIXED | |
ELEM-CONTENT |
名前空間を表すシンボル、あるいはURIを表すためにユーザが選んだ他のシンボルです。
前者の場合、URI-SYMBは不正なURI文字が%
でクォートされた
文字列をシンボルに変換したものです。
効力を持つ名前空間を表すリストです。リストの要素は、以下のフォームのうちの1つです。
(prefix uri-symb . uri-symb)
あるいは、
(prefix user-prefix . uri-symb)
user-prefixは、そのURIを表現するためにユーザにより選ばれたシンボル。
(#f user-prefix . uri-symb)
ユーザが選んだプリフィックスとuri-symbolの指定。
(*DEFAULT* user-prefix . uri-symb)
デフォルト名前空間の宣言。
(*DEFAULT* #f . #f)
デフォルト名前空間を宣言しない。この記法は、それ以前の宣言を上書き することを表す。
NAMESPACESのリストは、同じPREFIXについていくつかの要素を含むかも しれません。リストの先頭に近いものが効力を持ちます。
ペア(NAME . VALUE)の順序付きのコレクションで、NAMEは RES-NAMEかUNRES-NAMEです。このコレクションはADTです。
3引数の手続き (string1 string2 seed)
で、
新しいseedを返します。
この手続きは、文字データstring2が後に続く、文字データstring1を
扱うものです。string2は、“\n”や“”のような短い文字列です。
ペア (named-entity-name . named-entity-body)の連想リストで、
named-entity-nameはその実体が宣言されたシンボル、
named-entity-bodyは文字列か、(外部実体の場合は)
(そこから実体が読み込める)入力ポートを返す手続きです。
named-entity-bodyはまた、#f
かも知れません。
これは、named-entity-nameがその時点で展開されていることを
示します。
このnamed-entity-nameへの参照は、WFC非再帰違反としてエラーに
なります。
kindとtokenという2つのスロットを持つレコードです。 このレコードは、XML勧告によれば、「開始タグ、終了タグ、空要素タグ、 実体参照、文字参照、コメント、CDATAセクションの区切り、 文書型宣言、処理命令の形を取る」マークアップを表します。
TAG-KIND。
UNRES-NAME。’COMMENT
と’CDSECT
というkindのXMLトークンでは、
そのheadは#f
になります。
例を示します。
<P> => kind='START, head='P </P> => kind='END, head='P <BR/> => kind='EMPTY-EL, head='BR <!DOCTYPE OMF ...> => kind='DECL, head='DOCTYPE <?xml version="1.0"?> => kind='PI, head='xml &my-ent; => kind = 'ENTITY-REF, head='my-ent
文字参照は、対応する文字へと透過的に解決されるので、XMLトークンとしては 表現されません。
elems、entities、notationsという3つのスロットを持つレコードです。
このレコードは、XML文書のデータタイプを表現します。それは、 宣言された要素とその属性のリスト、宣言された記法、 解析済み一般実体の置換文字列やロードされる手続きのリストなどです。 通常、xml-declレコードは、それを作るには他にたくさんの方法 (例えばファイルからロードするなど)があるにも関わらず、DTDかXML Schemaから 作られます。
elems: decl-elemか#f
の(連想)リスト。後者は、パーザに、
要素と属性の妥当性検査を行わないように指示します。
decl-elem: 1つの要素の宣言:
(elem-name elem-content decl-attrs)
;
elem-nameはその要素のUNRES-NAME。
elem-contentはELEM-CONTENT-MODEL。
decl-attrsはATTLISTか、(attr-name . value)
の
連想リスト。
この要素は、要素のパージングを扱うユーザ手続きを宣言できます。
(例えば、カスタムな妥当性検査を行ったり、タグに出会うたびに
IDのハッシュを構築するなど。)
decl-attr: ATTLISTの要素で、1つの属性
(attr-name content-type use-type default-value)
の宣言:
attr-nameはその宣言された属性のUNRES-NAME、
content-typeはシンボルCDATA
、NMTOKEN、NMTOKENS、
あるいは列挙されたタイプの文字列のリスト。
use-typeはシンボルREQUIRED
、IMPLIED
、FIXED
。
default-valueは、デフォルト値としての文字列か、与えられなければ#f
。
{sxml.ssax
}
名前-値の属性リストを扱うユーティリティ手続きです。
{sxml.ssax
}
XML-TOKENレコードのコンストラクタと述語です。
これらは、プリミティブな字句解析ユニット(名前、空白、タグ)や、
より一般的な断片を扱います。
これらのパーザのほとんどは、適切なコンテキストで呼ばれなければなりません。
例えば、ssax:complete-start-tag
は、開始タグが検知されそのGI
が
読み込まれたときにのみ呼ばれなければなりません。
{sxml.ssax
}
次のように定義されるS(空白)をスキップします。
[3] S ::= (#x20 | #x9 | #xD | #xA)
この手続きは、portのスキャン中に遭遇した最初の空白ではない文字を 返します。この文字は、入力ストリームに残されます。
{sxml.ssax
}
NCName
がa-charで始まるかどうかを検査します。
{sxml.ssax
}
portで現在の位置から始まるNCName
を読み込み、それをシンボルとして
返します。
{sxml.ssax
}
(名前空間)完全修飾名、QName
をportの現在の位置から読み込みます。
REC-xml-namesは、
[6] QName ::= (Prefix ':')? LocalPart [7] Prefix ::= NCName [8] LocalPart ::= NCName
戻り値は、UNRES-NAMEです。
{sxml.ssax
}
定義済みのXML名前空間の接頭辞、つまり、’xml
です。
{sxml.ssax
}
この手続きは、マークアップトークンのパージングを開始します。
ストリームの現在の位置は、#\<
でなければなりません。
この手続きは、見ているマークアップトークンがどの種類のものか見当を
つけるに十分な程度、入力ストリームをスキャンします。
この手続きは、そのトークンを表現するxml-token構造を返します。
通常、その時点のマークアップの読み込みは完了していないことに注意して下さい。
特に、開始タグトークンの属性はスキャンされていません。
特定の値が返されたときの戻り値とportでの位置を詳細に説明します。
PI-token
PI
ターゲットのみが読み込まれました。
処理命令の読み込みを完了してそれを無視するためには、ssax:skip-pi
を呼びます。
(PI
の内容が、属性-値のペアの場合は、)ssax:read-attributes
も
便利です。
END-token
終了タグが完全に読み込まれました。
現在の位置は、終了の#\>
文字の直後です。
COMMENT
コメントが完全に読み込まれスキップされました。
現在の位置は、コメントが終了する“-->
”の直後です。
CDSECT
現在の位置は、"<!CDATA[
"の直後です。
残りを読むためには、ssax:read-cdata-body
を使います。
DECL
この宣言マークアップを識別するキーワード(“<!
”に続くもの)を
読み込んだところです。現在の位置は、(通常は空白文字である)
そのキーワードの直後です。
START-token
この開始タグのキーワード(GI
)を読み込んだところです。
属性はまだスキャンされていません。
また、このタグが空の要素を持つかどうかも分かりません。
このトークンのパージングを終了するためには、
ssax:complete-start-tag
を使います。
{sxml.ssax
}
現在の位置は、PI
の内側です。
PI
の残りをスキップします。
{sxml.ssax
}
現在の位置は、PITarget
を読み込んだ直後です。
PI
のボディを読み込んで、それを文字列として返します。
ポートでは、PI
を終了する’?>
’の直後の文字を指します。
[16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
{sxml.ssax
}
ポートでの現在の位置は、内部DTDサブセットの内側です
(例えば、内部DTDサブセットの始まりである#\[
を読み込んだところ)。
このDTDを終了する、組み合わせとなる“]>
”までをスキップします。
{sxml.ssax
}
この手続きは、CDATA
セクションを開始する文字列、"<![CDATA[
"を
読み込んだ後に呼ばれなければなりません。
現在の位置は、CDATA
のボディの最初の位置です。
この手続きは、CDATA
のボディのデータを読み込み、それらを
STR-HANDLER(文字データのコンシューマ)へ渡します。
str-handlerは、string1
string2 seedを取る手続き
STR-HANDLERです。
STR-HANDLERの最初の引数string1は、改行を含みません。
2番目の引数string2は、改行を含むことがよくあります。
STR-HANDLERの最初の呼び出しでは、seedはssax:read-cdata-body
の
第3引数として渡されるものです。
この最初の呼び出しの結果は、文字データのコンシューマの引数seedとして渡され、
以降同じように続きます。
STR-HANDLERの最後の呼び出しの結果は、ssax:read-cdata-body
から返されるものです。
基本的な’fold
’イテレータに似ています。
CDATA
セクションでは、以下の3つだけの例外を除いて、全ての文字は
その表面上の値を持ちます。
CR
、LF
、CRLF
は行区切りとして扱われ、STR-HANDLERへは
1つの#\newline
として渡されます。
]]>
”は、CDATA
セクションの終わりであると
されます。
>
は、#\>
文字の埋め込みとして扱われます。
<
と&
は特別なものとして認識されない(よって展開されない)ことに
注意が必要です!
{sxml.ssax
}
[66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'
この手続きは、文字参照を表す“&#
”を読み込んだ後に呼ばれなければ
なりません。
この手続きは、この参照を読み込んで対応する文字を返します。
portでの現在の位置は、文字参照の終わりとなる“;
”の後と
なります。
WFC: XML-Spec.html#wf-Legalchar
も参照のこと。
XML勧告のセクション“4.1 文字と実体参照”によると、
“[定義: 文字参照は、ISO/IEC 10646文字集合にある特定の文字を参照する。 例えば、利用できる入力デバイスからは直接アクセスできないものなど。]”
したがって、入力ストリームの現在の文字エンコーディングに関係なく、
文字コードを文字に変換するために関数ucscode->char
を使います。
{sxml.ssax
}
解析済み実体参照を展開し処理します。
戻り値は、content-handlerかstr-handlerから返された値です。
こちらも参照のこと。
WFC: XML-Spec.html#wf-entdeclared WFC: XML-Spec.html#norecursion
{sxml.ssax
}
この手続きは、Attribute*
を読み込みパーズします。
[41] Attribute ::= Name Eq AttValue [10] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'" [25] Eq ::= S? '=' S?
この手続きは、Name(UNRES-NAME)とValue(文字列)のペアである ATTLISTを返します。 portでの現在の文字は、NCNameの開始文字ではなく、空白ではない文字です。
’AttValue’を読み込むときには、以下のルールに留意して下さい。 “属性の値がアプリケーションに渡されるか妥当性が検査される前に、 XMLプロセッサはそれを以下のように正規化しなければならない:
#x20
、#xD
、#xA
、#x9
)は、
外部解析済み実体か内部解析済み実体のリテラルの実体の値の一部である
“#xD#xA
”のシーケンスにただ1つの#x20
が追加されることを
除いて、正規化された値に#x20
を追加することで処理される。
こちらも参照のこと。
WFC: XML-Spec.html#CleanAttrVals WFC: XML-Spec.html#uniqattspec
{sxml.ssax
}
与えられた適切なnamespacesの宣言を用いて、unres-nameを
res-nameに変換する。
最後の引数apply-default-ns?は、デフォルト名前空間の適用を行うか
どうかを決めます(例えば、属性名には適用しないなど)。
REC-xml-names/#nsc-NSDeclared
によれば、接頭辞“xml”は
名前空間名“http://www.w3.org/XML/1998/namespace”に定義済みで束縛されていると
されます。
この手続きは、名前空間の制約をテストします: http://www.w3.org/TR/REC-xml-names/#nsc-NSDeclared。
{sxml.ssax
}
uri-strを適切なシンボルに変換します。
{sxml.ssax
}
この手続きは、開始タグのマークアップのパージングを完了するためのものです。
この手続きは、開始タグトークンが読み込まれた後に呼ばれなければなりません。
tagはUNRES-NAMEです。
elemsはxml-decl::elems
のインスタンスで、
手続きに、要素とそれらの属性の妥当性検査を行わないように
指示するために、#f
を指定することができます。
この手続きはいくつかの値を返します。
RES-NAME。
要素の属性。(res-name . string)
というペアのATTLIST。
このリストは、xmlns
属性を含みません。
パージング中の開始タグに含まれる名前空間(再)宣言により修正された後の 名前空間の入力リスト。
終了時のportでの現在の位置は、開始タグのマークアップを終了する
#\>
の後になります。
こちらも参照のこと。
VC: XML-Spec.html#enum VC: XML-Spec.html#RequiredAttr VC: XML-Spec.html#FixedAttr VC: XML-Spec.html#ValueType WFC: XML-Spec.html#uniqattspec (after namespaces prefixes are resolved) VC: XML-Spec.html#elementvalid WFC: REC-xml-names/#dt-NSName
XML勧告では明示されていませんが、xmlnsとxmlns:属性は、 (そのデフォルト値を指定するために宣言されることが出来ますが) 宣言される必要がないことに注意して下さい。
{sxml.ssax
}
この手続きは、ExternalID
をパーズします。
[75] ExternalID ::= 'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'") [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'" [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
この手続きは、ExternalID
が期待されるところで呼ばれます。
つまり、現在の文字は、それぞれSYSTEM
かPUBLIC
トークンを開始する
#\S
か#\P
でなければなりません。
この手続きは、SystemLiteral
を文字列として返します。
PubidLiteral
は、存在したとしても無視されます。
これらは、全体的な実体(ドキュメント)あるいはその高レベルな断片 (プロローグ、ルート要素など)をパーズします。
{sxml.ssax
}
そのコンテキストでのMisc
をスキャンします。
[1] document ::= prolog element Misc* [22] prolog ::= XMLDecl? Misc* (doctypedec l Misc*)? [27] Misc ::= Comment | PI | S
以下の関数は、プロローグかエピローグのコンテキストで呼ばれます。
これらのコンテキストでは、空白文字は完全に無視されます。
ssax:scan-Misc
からの戻り値は、PI
トークンかDECL
トークン、
START
トークン、EOFのいずれかです。
コメントは無視され報告されません。
{sxml.ssax
}
この手続きは、XML文書かXML要素の文字内容を読むためのものです。
[43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
具体的には、この手続きはCharData
を読み込み、CDSect
と
文字実体を展開し、コメントをスキップします。
この手続きは、名前付き参照、EOF、PI
あるいは開始/終了タグの開始地点で
停止します。
読み込むポート。
EOFがノーマルかどうか、つまり、文字データがEOFで終わるかどうかを 表す真偽値。解析済み実体を処理している間はEOFはノーマル。
STR-HANDLER。
STR-HANDLERの最初の呼び出し時に渡される引数。
この手続きは2つの結果、seedとtokenを返します。
seedはstr-handlerの最後の呼び出しの結果、あるいは str-handlerが一度も呼ばれなかった場合はオリジナルのseedです。
tokenはEOFオブジェクト(これはexpect-eof?が#t
の場合のみ)か、
PI
の開始を表すxml-token。
このPI
の残りを読み込むかスキップするかはアプリケーションに
任される。
CDATA
セクションと文字参照はインラインで展開され返されません。
コメントは無視されます。
XML勧告が要求するように、文字データ中の全ての空白文字は保存されなければなりません。
しかし、CR
文字(#xD
)は、LF
文字(#A
)の前に現れるか
#xA
文字で置き換えられた場合は、無視されなければなりません。
XML勧告のセクション2.10と2.11を参照して下さい。
また、正規のXML勧告も参照して下さい。
{sxml.ssax
}
tokenが、予想されたkindのもので、予想されたgiを
持つことを確認します。gi引数は、実際には2つのシンボル、
名前空間URIかその接頭辞と、そのローカル名のペアでしょう。
アサーションが失敗したら、error-contに3つの引数、token kind gi
を渡されて評価されます。
error-contの結果が返されます。
これらのパーザは、SSAXパーザをインスタンス化するための構文的フォームのセットです。
ユーザは、完全な妥当性検査、妥当性検査なし、特定の妥当性検査を行うために
このパーザをインスタンス化できます。
ユーザは、どのPI
について通知されたいかを指定します。
ユーザは、解析済み文字と要素のデータで何をしたいかを知らせます。
後者のハンドラは、パージングがSAXやDOMモデルに従うかを決定します。
{sxml.ssax
}
1つの処理命令(PI
)をパーズして処理するパーザを作ります。
my-pi-handlers:
(PI-TAG . PI-HANDLER)のペアの連想リスト。
PI-TAGはNCNameのシンボル、PI
ターゲット。
PI-HANDLERはport pi-tag seedを引数とする手続きで、
portではPI
ターゲットの後の最初のシンボルを指しています。
ハンドラは、PI
を終了する組み合わせとなる’?>
’を含む、
PI
の残りを読み込みます。ハンドラは新しいseedを返します。
PI-TAGの1つは、シンボル*DEFAULT*
でしょう。
これに対応するハンドラは、他のハンドラが扱わないPI
を処理します。
*DEFAULT*
PI-TAGが指定されていない場合は、
ssax:make-pi-parser
は、PI
のボディをスキップするパーザを
作ります。
ssax:make-pi-parser
が返すのは、port pi-tag seedを
取る手続きで、ユーザ指定のハンドラに従い現在のPI
をパーズします。
{sxml.ssax
}
その文字内容や子要素をも含む1つの要素をパーズし処理するパーザを作ります。
このパーザは通常、ドキュメントのルート要素の適用されます。
elem-gi attributes namespaces expected-content seed
を引数に取る手続きで、elem-giは処理されようとしている要素のRES-NAMEです。
この手続きは、要素の内容を処理するハンドラに渡されるseedを生成します。
elem-gi attributes namespaces parent-seed seed
を引数に取る手続きです。この手続きは、elem-giのパージングが完了した時に
呼ばれます。
seedは、最後に呼ばれたパーザからの(あるいは、
要素が空要素であった場合は、my-new-level-seedからの)結果です。
parent-seedは、my-new-level-seedへ渡されたのと同じseedです。
この手続きは、パーザの結果となるseedを生成するためのものです。
STR-HANDLER。
ssax:make-pi-handler
を参照して下さい。
生成されたパーザは:
start-tag-head port elems entities namespaces
preserve-ws? seed
を引数に取る手続きです。
この手続きは、開始タグのトークンが読み込まれた後に呼ばれなければなりません。
start-tag-headは要素の開始タグのUNRES-NAMEです。
elemsはxml-decl::elems
のインスタンスです。
ssax:complete-start-tag::preserve-ws?
も参照して下さい。
こちらも参照のこと。
VC: XML-Spec.html#elementvalid WFC: XML-Spec.html#GIMatch
{sxml.ssax
}
XMLパージングフレームワークのインスタンスである、XMLパーザを作ります。
これは、提供されるユーザハンドラによって、SAX、DOM、あるいは特化された
パーザになります。
user-handler-tagはシンボルで、タグに続く手続き的な式を識別します。 以下にタグと対応する手続きのシグネチャを示します。 全てのタグが指定される必要はありません。 いくつかが省略されると、合理的なデフォルトのものが適用されます。
tag: DOCTYPE
ハンドラ手続きの引数: port docname systemid internal-subset? seed
internal-subset?が#t
なら、ポートでの現在の位置は内部DTDサブセットの
開始となる#\[
を読んだ直後です。
手続きから戻る前に、このサブセットの残りの読み込みを完了しなければなりません
(あるいは、それを読むことに興味がなければ、skip-internal-subsetを呼ばなければなりません)。
終了時のポートでの位置は、DOCTYPE宣言全体のあとの最初のシンボルでなければなりません。
ハンドラ手続きは4つの値:
elems entities namespaces seed
を生成しなければなりません。
elemsについては、xml-decl::elems
を参照して下さい。
妥当性検査をオフにするためには、#f
になるでしょう。
namespacesは、通常、選択されたURI-SYMBに対してUSER-PREFIXを含む
でしょう。
デフォルトのハンドラ手続きは、内部サブセットがあってもそれをスキップし、
(values #f '() '() seed)
を返します。
tag: UNDECL-ROOT
ハンドラ手続きの引数: elem-gi seed
elem-giはルート要素のUNRES-NAMEです。
この手続きは、パージング中のXML文書がDOCTYPE
宣言を含まない時に
呼ばれます。
ハンドラ手続きは、上ではDOCTYPEハンドラですが、4つの値:
elems entities namespaces seed
を生成しなければなりません。
デフォルトのハンドラ手続きは、(values #f '() '() seed)
を返します。
tag: DECL-ROOT
ハンドラ手続きの引数: elem-gi seed
elem-giは、ルート要素のUNRES-NAMEです。
この手続きは、パージング中のXML文書がDOCTYPE
宣言を含む場合に呼ばれます。
このハンドラ手続きは、新しいseed
を生成しなければなりません
(そして、ハンドラが望めば、ルート要素の名前がDOCTYPEにマッチするかを
検証します)。
デフォルトのハンドラ手続きは、それ自身を返す手続きです。
tag: NEW-LEVEL-SEED
ハンドラ手続きの引数: ssax:make-elem-parser
とmy-new-level-seedを参照して下さい。
tag: FINISH-ELEMENT
ハンドラ手続きの引数: ssax:make-elem-parser
とmy-finish-elementを参照して下さい。
tag: CHAR-DATA-HANDLER
ハンドラ手続きの引数: ssax:make-elem-parser
とmy-char-data-handlerを参照して下さい。
tag: PI
ハンドラ手続きの引数: ssax:make-pi-parser
を参照して下さい。
デフォルトの値は、'()
です。
生成されるパーザは、
PORT SEEDを取る手続き、
です。
この手続きは、ドキュメントのプロローグをパーズして、 その残りを処理するために(ssax:make-elem-parserで作られた)パーザへ 引き継いで終了します。
[1] document ::= prolog element Misc* [22] prolog ::= XMLDecl? Misc* (doctypedec | Misc*)? [27] Misc ::= Comment | PI | S [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S? ('[' (markupdecl | PEReference | S)* ']' S?)? '>' [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl | NotationDecl | PI | Comment
いくつかの便利なユーティリティ手続きがあります。
{sxml.ssax
}
fragments(そのいくつかはテキスト文字列)のリストを渡すと、
そのリストを逆順にして隣り合ったテキスト文字列を連結します。
{sxml.ssax
}
fragments(そのいくつかはテキスト文字列)のリストを渡すと、
そのリストを逆順にして隣り合ったテキスト文字列を連結します。
“重要でない”空白文字、つまり、最初や最後、要素の間にある空白文字を
削除します。文字データに含まれる空白文字には影響を与えません。
この手続きは、パーズされたSXMLにある“重要でない”空白文字を
“知的に”削除するために使います。空白文字に関して、厳密に
XML勧告に準拠したい場合は、代わりに手続き
ssax:reverse-collect-str
を使って下さい。
{sxml.ssax
}
これは、上のSSAXパーザのインスタンスで、portから読み込まれる
XMLドキュメントのSXML表現を返します。
namespace-prefix-assigは、(USER-PREFIX . URI-STRING)
のリストで、特定のURI-STRINGで識別されるある名前空間を
USER-PREFIXに割り当てます。これは空リストでも構いません。
この手続きは、SXMLツリーを返します。
ポートでの位置は、ルート要素の後の最初の文字を指します。
簡単な例を示します:
(call-with-input-string "<book> <title>Land of Lisp</title> <author>Conrad Barski</author> <publisher>No Starch Press</publisher> </book> <book> <title>Programming Gauche</title> <author>Kahua Project</author> <author>Shiro Kawai</author> <publisher>O'Reilly Japan</publisher> </book>" (^p (ssax:xml->sxml p '()))) ⇒ (*TOP* (book (title "Land of Lisp") (author "Conrad Barski") (publisher "No Starch Press")) (book (title "Programming Gauche") (author "Kahua Project") (author "Shiro Kawai") (publisher "O'Reilly Japan")))
ドキュメントは複数のトップレベルノードを持っている場合があるので、
ドキュメント全体は擬似ノード*TOP*
の下にまとめられます。
*TOP*
ノードはまたメタ情報を保持するのにも使われます。
次の例ではXML宣言が*PI*
(processing infomation) ノードとして
パーズされています。
(call-with-input-string "<?xml version=\"1.0\" encoding=\"utf-8\"?> <book> <title>Programming Gauche</title> <author>Kahua Project</author> <author>Shiro Kawai</author> <publisher>O'Reilly Japan</publisher> </book>" (^p (ssax:xml->sxml p '()))) ⇒ (*TOP* (*PI* xml "version=\"1.0\" encoding=\"utf-8\"") (book (title "Programming Gauche") (author "Kahua Project") (author "Shiro Kawai") (publisher "O'Reilly Japan")))
名前空間も認識されます。デフォルトでは名前空間のエイリアスは全て 完全なURIへと展開されます:
(call-with-input-string "<b:book xmlns:b=\"https://example.com/book/\"> <b:title>Programming Gauche</b:title> <b:author>Kahua Project</b:author> <b:author>Shiro Kawai</b:author> <b:publisher>O'Reilly Japan</b:publisher> </b:book>" (^p (ssax:xml->sxml p '()))) ⇒ (*TOP* (https://example.com/book/:book (https://example.com/book/:title "Programming Gauche") (https://example.com/book/:author "Kahua Project") (https://example.com/book/:author "Shiro Kawai") (https://example.com/book/:publisher "O'Reilly Japan")))
(名前空間エイリアスは入れ子になったスコープを持つため、 ただエイリアスをそのまま保持するだけでは情報が失われるためです。)
ただ、完全なURIに展開された名前空間プレフィクスは扱い辛いので、 独自の名前空間エイリアスをnamespace-prefix-assig引数で指定できます。
(call-with-input-string "<b:book xmlns:b=\"https://example.com/book/\"> <b:title>Programming Gauche</b:title> <b:author>Kahua Project</b:author> <b:author>Shiro Kawai</b:author> <b:publisher>O'Reilly Japan</b:publisher> </b:book>" (^p (ssax:xml->sxml p '((Book . "https://example.com/book/"))))) ⇒ (*TOP* (@ (*NAMESPACES* (Book "https://example.com/book/"))) (Book:book (Book:title "Programming Gauche") (Book:author "Kahua Project") (Book:author "Shiro Kawai") (Book:publisher "O'Reilly Japan")))