Skip to main content

This is documentation for Caché & Ensemble. See the InterSystems IRIS version of this content.Opens in a new tab

For information on migrating to InterSystems IRISOpens in a new tab, see Why Migrate to InterSystems IRIS?

%XML.TextReader の使用

%XML.TextReaderOpens in a new tab クラスを使用すると、Caché オブジェクトに直接マップされているまたはされていない可能性がある任意の XML ドキュメントを、単純で簡単な方法で読み取ることができます。具体的には、このクラスを使用すると、適格な形式の XML ドキュメントをナビゲートし、その中の情報 (要素、属性、コメント、ネームスペース URI など) を表示できます。このクラスは、DTD、もしくは XML スキーマを基にした、ドキュメントの完全な検証も提供します。ただし、%XML.ReaderOpens in a new tab と異なり、%XML.TextReaderOpens in a new tab には DOM を返す方法が用意されていません。DOM が必要な場合は、このドキュメント内で前述の “Caché オブジェクトへの XML のインポート” の章を参照してください。

以下の項目について説明します。

Note:

使用する任意の XML ドキュメントの XML 宣言にはそのドキュメントの文字エンコードを明記する必要があり、明記しておけば、ドキュメントは宣言どおりにエンコードされるようになります。文字エンコードが宣言されていない場合は、このドキュメント内の前述の “入出力の文字エンコード” で説明されている既定値が使用されます。これらの既定値が正しくない場合は、XML 宣言を修正して、実際に使用されている文字セットを指定するようにします。

テキスト・リーダ・メソッドの作成

Caché オブジェクト・クラスとのリレーションシップが必ずしもあるとは限らない任意の XML ドキュメントを読み取るには、%XML.TextReaderOpens in a new tab クラスのメソッドを呼び出します。これにより、ドキュメントを開き、テキスト・リーダ・オブジェクトとして一時的な格納場所にロードします。テキスト・リーダ・オブジェクトには、ナビゲート可能なノードのツリーが含まれ、そのそれぞれにソース・ドキュメントについての情報が含まれています。そのため、記述したメソッドでドキュメントをナビゲートし、ドキュメントに関する情報を検出できます。このオブジェクトのプロパティは、ドキュメント内の現在の場所に応じて、そのドキュメントに関する情報を提示します。検証エラーがある場合、それらのエラーはツリー内のノードとしても表示できます。

全体構造

メソッドは以下の操作の一部またはすべてを実行する必要があります。

  1. 以下のメソッドのいずれかの最初の引数を使用して、ドキュメント・ソースを指定します。

    メソッド 最初の引数
    ParseFile() 完全なパスを含むファイル名ファイル名およびパスは ASCII 文字のみを含む必要があります。
    ParseStream() ストリーム
    ParseString() 文字列
    ParseURL() URL

    どのような場合でも、ソース・ドキュメントは、適格な XML ドキュメント、つまり、XML 構文の基本的な規約に従ったドキュメントである必要があります。これらのメソッドはそれぞれ、結果が成功だったかどうかを示すステータス ($$$OK または失敗コード) を返します。通常のメカニズムでステータスをテストできます。特に、$System.Status.DisplayError(status) を使用して、エラー・メッセージのテキストを表示できます。

    メソッドは $$$OK を返す場合、これらのメソッドのそれぞれに対し、参照 (2 番目の引数) によって、XML ドキュメント内の情報を含むテキスト・リーダ・オブジェクトを返します。

    引数をさらに追加すると、エンティティの解析、検証、検出された項目などを制御できます。これらは、この章の後半の “解析メソッドの引数リスト” で説明しています。

  2. 解析メソッドで返されたステータスを確認し、必要に応じて実行を中止します。

    解析メソッドが $$$OK を返した場合、テキスト・リーダ・オブジェクトはソース XML ドキュメントに対応しています。このオブジェクトはナビゲートできます。

    ドキュメントには多くの場合、"element""endelement""startprefixmapping" などのノードが含まれています。ノード・タイプは、この章で後述する “ノード・タイプ” にリストが記載されています。

    Important:

    どのような検証エラーが発生した場合でも、ドキュメントには "error" ノードまたは "warning" ノードが含まれています。そのようなノードがないか、コードで確認する必要があります。“検証の実行” を参照してください。

  3. 以下のインスタンス・メソッドのいずれかを使用して、ドキュメントの読み取りを開始します。

    • ドキュメントの最初のノードへ移動するには、Read() を使用します。

    • 特定のタイプの最初の要素へ移動するには、ReadStartElement() を使用します。

    • "chars" の最初のノードへ移動するには、MoveToContent() を使用します。

    この章内で後述の “ドキュメントのナビゲート” を参照してください。

  4. このノードで関係するプロパティの値があれば、それを取得します。利用可能なプロパティには、NameValueDepth などがあります。この章内で後述の “ノード・プロパティ” を参照してください。

  5. 必要に応じてドキュメントのナビゲートおよびプロパティ値の取得を続けます。

    現在のノードが要素の場合、MoveToAttributeIndex() または MoveToAttributeName() メソッドを使用して、要素の属性にフォーカスを移動できます。要素に戻るには、該当する場合は MoveToElement() を使用します。

  6. 必要に応じて、Rewind() メソッドを使用して、ドキュメントの最初 (最初のノードの前) に戻ります。これは、ソース内を後退できる唯一のメソッドです。

メソッドの実行後、テキスト・リーダは消滅し、関連する一時格納場所もすべてクリーンアップされます。

例 1

ここでは、任意の XML ファイルを読み取り、各ノードのシーケンス番号、タイプ、名前、および値を表示する単純なメソッドを示します。

ClassMethod WriteNodes(myfile As %String)
{
    set status=##class(%XML.TextReader).ParseFile(myfile,.textreader)
    //check status
    if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
    //iterate through document, node by node
    while textreader.Read()
    {
        Write !, "Node ", textreader.seq, " is a(n) "
        Write textreader.NodeType," "
        If textreader.Name'=""
        {
            Write "named: ", textreader.Name
            }
            Else
            {
                Write "and has no name"
                }
        Write !, "    path: ",textreader.Path
        If textreader.Value'="" 
        {
            Write !, "    value: ", textreader.Value
            }
        }
}

この例は、以下を実行します。

  1. ParseFile() クラス・メソッドを呼び出します。このメソッドはソース・ファイルを読み取り、テキスト・リーダ・オブジェクトを生成して、変数 doc 内でそのオブジェクトを参照によって返します。

  2. ParseFile() が成功した場合、このメソッドは Read() メソッドを実行して、ドキュメント内で次のノードをそれぞれ検索します。

  3. 各ノードについて、このメソッドは、そのノードのシーケンス番号、ノード・タイプ、ノード名 (存在する場合)、ノード・パス、およびノード値 (存在する場合) が含まれた出力行を記述します。現在のデバイスに出力されます。

以下の例のソース・ドキュメントを考えてみます。

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="mystyles.css"?>
<Root>
   <s01:Person xmlns:s01="http://www.root.org">
      <Name attr="xyz">Willeke,Clint B.</Name>
      <DOB>1925-10-01</DOB>
   </s01:Person>
</Root>

このソース・ドキュメントについては、前述のメソッドで以下の出力が生成されます。

Node 1 is a(n) processinginstruction named: xml-stylesheet
    path:
    value: type="text/css" href="mystyles.css"
Node 2 is a(n) element named: Root
    path: /Root
Node 3 is a(n) startprefixmapping named: s01
    path: /Root
    value: s01 http://www.root.org
Node 4 is a(n) element named: s01:Person
    path: /Root/s01:Person
Node 5 is a(n) element named: Name
    path: /Root/s01:Person/Name
Node 6 is a(n) chars and has no name
    path: /Root/s01:Person/Name
    value: Willeke,Clint B.
Node 7 is a(n) endelement named: Name
    path: /Root/s01:Person/Name
Node 8 is a(n) element named: DOB
    path: /Root/s01:Person/DOB
Node 9 is a(n) chars and has no name
    path: /Root/s01:Person/DOB
    value: 1925-10-01
Node 10 is a(n) endelement named: DOB
    path: /Root/s01:Person/DOB
Node 11 is a(n) endelement named: s01:Person
    path: /Root/s01:Person
Node 12 is a(n) endprefixmapping named: s01
    path: /Root
    value: s01
Node 13 is a(n) endelement named: Root
    path: /Root

コメントが無視されていることに注意してください。既定では、%XML.TextReaderOpens in a new tab クラスはコメントを無視します。この変更の詳細は、この章で後述する“解析メソッドの引数リスト” で説明します。

例 2

以下の例では、XML ファイルを読み取り、その中の各要素をリスト表示します。

ClassMethod ShowElements(myfile As %String)
{
    set status = ##class(%XML.TextReader).ParseFile(myfile,.textreader)
    //check status
    if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
    //iterate through document, node by node
    while textreader.Read()
    {
        if (textreader.NodeType = "element") 
        {
            write textreader.Name,!
            }
        }
}

このメソッドは、NodeType プロパティを使用して、各ノードのタイプをチェックします。そのノードが要素の場合、メソッドはその名前を現在のデバイスに出力します。前述の XML ソース・ドキュメントについては、このメソッドで以下の出力が生成されます。

Root
s01:Person
Name
DOB

ノード・タイプ

ドキュメントのノードはそれぞれ、以下のタイプのいずれかになります。

テキスト・リーダ・ドキュメントのノード・タイプ
タイプ 説明
"attribute" XML 属性
"chars" 文字一式 (要素のコンテンツなど)

%XML.TextReaderOpens in a new tab クラスは、他のノード・タイプ ("CDATA""EntityReference"、および "EndEntity") を認識しますが、それらを "chars" に自動的に変換します。

"comment" XML コメント
"element" XML 要素の先頭
"endelement" XML 要素の終了
"endprefixmapping" ネームスペースが宣言されているコンテキストの終了
"entity" XML エンティティ
"error" パーサで検出された検証エラー。“検証の実行” を参照してください。
"ignorablewhitespace" 混在するコンテンツ・モデルのマークアップ間にある空白
"processinginstruction" XML 処理命令
"startprefixmapping" ネームスペースを含むまたは含まない可能性がある、XML ネームスペース宣言
"warning" パーサで検出された検証の警告。“検証の実行” を参照してください。

1 つの XML 要素が複数のノードで構成されていることに注意してください。例えば、以下の XML フラグメントを考えてみます。

<Person>
   <Name>Willeke,Clint B.</Name>
   <DOB>1925-10-01</DOB>
</Person>

SAX パーサは、この XML を以下のノードのセットとして表示します。

ドキュメント・ノードの例
ノード番号 ノードのタイプ ノード名 (存在する場合) ノードの値 (存在する場合)
1 element Person  
2 element Name  
3 chars   Willeke,Clint B.
4 endelement Name  
5 element DOB  
6 chars   1925-10-01
7 endelement DOB  
8 endelement Person  

例えば <DOB> 要素は、element ノード、chars ノード、および endelement ノードの 3 つのノードであると見なされることに注意してください。また、この要素のコンテンツは、chars ノードの値としてのみ使用できることにも注意してください。

ノード・プロパティ

前述のように、%XML.TextReaderOpens in a new tab クラスは XML ドキュメントを解析し、ドキュメントのコンポーネントに対応するノードのセットで構成されるテキスト・リーダ・オブジェクトを作成します。ノード・タイプは、この章で前述している “ドキュメント・ノード” で説明しています。

別のノードにフォーカスを変更すると、そのテキスト・リーダ・オブジェクトのプロパティが更新され、現在調べているノードについての情報が含められます。ここでは、%XML.TextReaderOpens in a new tab クラスのすべてのプロパティについて説明します。

AttributeCount

現在のノードが要素または属性の場合、このプロパティは、要素の属性の番号を示します。任意の要素内で最初の属性の番号は 1 となります。

その他のタイプのノードでは、このプロパティは 0 になります。

Depth

ドキュメント内での現在のノードの深さを示します。ルート要素の深さは 1 です。ルート要素外の項目の深さは 0 です。属性は、それが属する要素と同じ深さにあることに注意してください。同様に、エラーまたは警告は、そのエラーまたは警告を引き起こした項目と同じ深さになります。

EOF

リーダがソース・ドキュメントの末尾に到達した場合は True、それ以外の場合は False です。

HasAttributes

現在のノードが要素の場合、その要素に属性があれば、このプロパティは True です (属性がなければ False です)。現在のノードが属性の場合、このプロパティは True です。

その他のタイプのノードでは、このプロパティは False になります。

HasValue

現在のノードが値を持つタイプのノードの場合 (その値が Null であっても)、True です。それ以外の場合、このプロパティは False です。具体的には、このプロパティは以下のタイプのノードでは True となります。

  • attribute

  • chars

  • comment

  • entity

  • ignorablewhitespace

  • processinginstruction

  • startprefixmapping

エラーおよび警告のタイプのノードについては、それらのノード・タイプに値があっても、HasValue は False となることに注意してください。

IsEmptyElement

現在のノードが要素であり、空白である場合には True です。それ以外の場合、このプロパティは False です。

LocalName

attribute、element、または endelement のタイプのノードの場合、これは現在の要素または属性の名前からネームスペースの接頭語を除いたものとなります。その他すべてのタイプのノードでは、このプロパティは Null になります。

Name

ノードのタイプに応じた、現在のノードの完全修飾名です。以下のテーブルに詳細を示します。

タイプごとのノード名
ノード・タイプ 名前と例
attribute 属性の名前。例えば、次のような属性の場合、

groupID="GX078"

Name は次のようになります。

groupID

element

または

endelement

要素の名前。例えば、次のような要素の場合、

<s01:Person groupID="GX078">...</s01:Person>

Name は次のようになります。

s01:Person

entity エンティティの名前
startprefixmapping

または

endprefixmapping

接頭語 (存在する場合)。例えば、次のようなネームスペース宣言の場合、

xmlns:s01="http://www.root.org"

Name は次のようになります。

s01

別の例では、次のようなネームスペース宣言の場合、

xmlns="http://www.root.org"

Name は Null になります。

processinginstruction 処理命令のターゲット。例えば、次のような処理命令の場合、

<?xml-stylesheet type="text/css" href="mystyles.css"?>

Name は次のようになります。

xml-stylesheet

その他すべてのタイプ null
NamespaceUri

attribute、element、または endelement のタイプのノードの場合、これは属性または要素が属するネームスペース (存在する場合) となります。その他すべてのタイプのノードでは、このプロパティは Null になります。

NodeType

現在のノードのタイプ。この章で前述した “ドキュメント・ノード” を参照してください。

Path

要素のパス。例えば、以下の XML ドキュメントを考えてみます。

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="mystyles.css"?>
<s01:Root xmlns:s01="http://www.root.org" xmlns="www.default.org">
   <Person>
      <Name>Willeke,Clint B.</Name>
      <DOB>1925-10-01</DOB>
      <GroupID>U3577</GroupID>
      <Address xmlns="www.address.org">
         <City>Newton</City>
         <Zip>56762</Zip>
      </Address>
   </Person>
</s01:Root>

City 要素の Path プロパティは /s01:Root/Person/Address/City です。他の要素も同様に処理されます。

ReadState

テキスト・リーダ・オブジェクトの全体の状態を、以下のいずれかで示します。

  • "Initial" は、Read() メソッドがまだ呼び出されていないことを示します。

  • "Interactive" は、Read() メソッドが少なくとも 1 回呼び出されたことを示します。

  • "EndOfFile" は、ファイルの末尾に達したことを示します。

ノードのタイプに応じた、現在のノードの値 (存在する場合) です。以下のテーブルに詳細を示します。

タイプごとのノードの値
ノード・タイプ 値と例
attribute 属性の値例えば、次のような属性の場合、

groupID="GX078"

Value は次のようになります。

GX078

chars テキスト・ノードのコンテンツ例えば、次のような要素の場合、

<DOB>1925-10-01</DOB>

chars ノードでは、Value は次のようになります。

1925-10-01

comment コメントのコンテンツ例えば、次のようなコメントの場合、

<!--Comment here-->

Value は次のようになります。

Comment here

entity エンティティの定義
error エラー・メッセージ。例えば、この章で後述する “検証の実行” を参照してください。
ignorablewhitespace 空白のコンテンツ
processinginstruction ターゲット以外の処理命令全体のコンテンツ例えば、次のような処理命令の場合、

<?xml-stylesheet type="text/css" href="mystyles.css"?>

Value は次のようになります。

type="text/css" href="mystyles.css"?

startprefixmapping 接頭語の後にスペース文字が 1 つ、その後に URI が続きます。例えば、次のようなネームスペース宣言の場合、

xmlns:s01="http://www.root.org"

Value は次のようになります。

s01 http://www.root.org

warning 警告メッセージ。例えば、この章で後述する “検証の実行” を参照してください。
その他すべてのタイプ (element を含む) null
seq

ドキュメント内のこのノードのシーケンス番号。最初のノードの番号は 1 です。属性には、それが属する要素と同じシーケンス番号が割り当てられていることに注意してください。

解析メソッドの引数リスト

ドキュメント・ソースを解析するには、テキスト・リーダの ParseFile()ParseStream()ParseString()、または ParseURL() メソッドを使用します。どのような場合でも、ソース・ドキュメントは、適格な XML ドキュメント、つまり、XML 構文の基本的な規約に従ったドキュメントである必要があります。これらのメソッドでは、最初の 2 つの引数のみが必要となります。参考までに、これらのメソッドの引数を以下に順番に示します。

  1. FilenameStreamString、または URL — ドキュメント・ソース。

    ParseFile() では、Filename 引数には ASCII 文字のみを含む必要があります。

  2. TextReader — テキスト・リーダ・オブジェクト。メソッドが $$$OK を返す場合に、出力パラメータとして返されます。

  3. Resolver — ソースの解析時に使用されるエンティティ・リゾルバ。詳細は、“SAX パーサの使用法のカスタマイズ” の章の “カスタム・エンティティの解析実行” を参照してください。

  4. Flags — SAX パーサによる検証と処理を制御するフラグまたはフラグの組み合わせ。詳細は、“SAX パーサの使用法のカスタマイズ” の章の “パーサ・フラグの設定” を参照してください。

  5. Mask — XML ソース内の目的の項目を指定するためのマスク。詳細は、“SAX パーサの使用法のカスタマイズ” の章の “イベント・マスクの指定” を参照してください。

    Tip:

    %XML.TextReaderOpens in a new tab の解析メソッドでは、既定のマスクは $$$SAXCONTENTEVENTS です。これはコメントを無視することに注意してください。可能性のあるタイプのノードをすべて解析するには、この引数に $$$SAXALLEVENTS を使用します。これらのマクロは、%occSAX.inc インクルード・ファイルで定義します。

  6. SchemaSpec — ドキュメント・ソースの検証の基準となるスキーマ仕様。この引数は、ネームスペース/URL のペアをコンマで区切って指定したリストを含む文字列です。

    "namespace URL,namespace URL"
    

    ここで、namespace はスキーマに使用する XML ネームスペースで、URL はスキーマ・ドキュメントの位置を表す URL です。ネームスペースと URL の値の間は、1 つの空白文字で区切られています。

  7. KeepWhiteSpace — 空白を保持するかどうかを指定するオプション。

  8. pHttpRequest — (ParseURL() メソッドのみ) %Net.HttpRequestOpens in a new tab のインスタンスとしての、Web サーバへの要求。既定では、システムは %Net.HttpRequestOpens in a new tab の新規インスタンスを作成してそれを使用しますが、代わりに、%Net.HttpRequestOpens in a new tab の別のインスタンスで要求を行うことができます。これは、既存の %Net.HttpRequestOpens in a new tab があり、プロキシおよびその他のプロパティが既に設定されている場合に役立ちます。このオプションは、http のタイプの (file や ftp などではない) URL にのみ適用されます。

    %Net.HttpRequestOpens in a new tab の詳細は、"Caché インターネット・ユーティリティの使用法" のドキュメントを参照してください。または、%Net.HttpRequestOpens in a new tab のクラス・ドキュメントを参照してください。

ドキュメントのナビゲート

ドキュメントをナビゲートするには、テキスト・リーダの Read()ReadStartElement()MoveToAttributeIndex()MoveToAttributeName()MoveToElement()MoveToContent()、および Rewind() メソッドを使用します。

次のノードへの移動

ドキュメント内の次のノードに進むには、Read() メソッドを使用します。Read() メソッドは、前方のノードが存在しなくなるまで (つまり、ドキュメントの末尾に達するまで)、True の値を返します。前述の例では、このメソッドを以下のようなループで使用しました。

 While (textreader.Read()) {

...

 }

特定の要素の最初の出現箇所への移動

ドキュメント内の特定の要素の、最初の出現箇所に移動できます。この操作には、ReadStartElement() メソッドを使用します。このメソッドは、要素が検出されなくなるまで True の値を返します。要素が検出されない場合、メソッドはファイルの末尾に達しています。

ReadStartElement() メソッドは、要素名および (オプションで) ネームスペース URI の 2 つの引数をとります。%XML.TextReaderOpens in a new tab クラスはネームスペースの接頭語を処理しないことに注意してください。これにより、ReadStartElement() メソッドでは以下の 2 つの要素の名前が異なると見なします。

<Person>Smith,Ellen W. xmlns="http://www.person.org"</Person>

<s01:Person>Smith,Ellen W. xmlns:s01="http://www.person.org"</s01:Person>

属性への移動

要素に移動すると、その要素に属性がある場合は、以下の 2 つの方法のいずれかでその属性に移動できます。

  • MoveToAttributeIndex() メソッドを使用して、インデックス (要素内の属性の通常の位置) により特定の属性に移動します。このメソッドの引数は、属性のインデックス番号のみです。AttributeCount プロパティを使用して、指定された要素内の属性の数を知ることができます。すべてのプロパティのリストについては、この章で後述する “ノード・プロパティ” を参照してください。

  • MoveToAttributeName() メソッドを使用して、名前により特定の属性に移動します。このメソッドは、属性名および (オプションで) ネームスペース URI の 2 つの引数をとります。%XML.TextReaderOpens in a new tab クラスはネームスペースの接頭語を処理しないことに注意してください。属性に接頭語がある場合、その接頭語は属性名の一部と見なされます。

現在の要素に対する属性を終了したら、Read() などの検索メソッドを実行することで、ドキュメント内の次の要素に移動できます。また、MoveToElement() メソッドを実行して、現在の属性を含む要素に戻ることもできます。

例えば、以下のコードは、インデックス番号によって、現在のノードに対するすべての属性をリストにします。

 If (textreader.NodeType = "element") {
     // list attributes for this node
     For a = 1:1:textreader.AttributeCount {
         Do textreader.MoveToAttributeIndex(a)
         Write textreader.LocalName," = ",textreader.Value,!
     }
 }

以下のコードは、現在のノードに対する color 属性の値を検索します。

 If (textreader.NodeType = "element") {
     // find color attribute for this node
     If (textreader.MoveToAttributeName("color")) {
         Write "color = ",textreader.Value,!
     }
 }

コンテンツを含む次のノードへの移動

MoveToContent() メソッドはコンテンツの検出に役立ちます。具体的には以下のとおりです。

  • ノードのタイプが "chars" 以外の場合、このメソッドは "chars" タイプの次のノードに進みます。

  • ノードのタイプが "chars" の場合、このメソッドはファイル内で先に進みません。

巻き戻し

ここで説明するメソッドは、Rewind() メソッドを除き、すべてドキュメント内を前進します。Rewind() メソッドは、ドキュメントの最初に移動し、すべてのプロパティをリセットします。

検証の実行

既定では、ソース・ドキュメントは指定された任意の DTD またはスキーマ・ドキュメントに対して検証されます。ドキュメントに DTD セクションが含まれる場合、そのドキュメントはその DTD に対して検証されます。代わりに、スキーマ・ドキュメントに対して検証するには、“解析メソッドの引数リスト” で説明するように、ParseFile()ParseStream()ParseString()、または ParseURL() の引数リスト内でスキーマを指定します。

ほとんどのタイプの検証の問題は致命的ではなく、エラーまたは警告のいずれかを発生させます。具体的には、タイプが "error" または "warning" のノードが、ドキュメント・ツリーのエラーが発生した場所に自動的に追加されます。こうしたノードには、他のタイプのノードと同様に移動し、調査できます。

例えば、以下の XML ドキュメントを考えてみます。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Root [
  <!ELEMENT Root (Person)>
  <!ELEMENT Person (#PCDATA)>
]>
<Root>
   <Person>Smith,Joe C.</Person>
</Root>

この場合、検証エラーは予期されません。この章で前述したメソッド例 WriteNodes() を思い出してください。そのメソッドを使用してこのドキュメントを読み取る場合、出力は以下のようになります。

Node 1 is a(n) element named: Root
    and has no value
Node 2 is a(n) ignorablewhitespace and has no name
    with value:
 
Node 3 is a(n) element named: Person
    and has no value
Node 4 is a(n) chars and has no name
    with value: Smith,Joe C.
Node 5 is a(n) endelement named: Person
    and has no value
Node 6 is a(n) ignorablewhitespace and has no name
    with value:
 
Node 7 is a(n) endelement named: Root
    and has no value

一方、ファイルは以下のようになるとします。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Root [
  <!ELEMENT Root (Person)>
  <!ELEMENT Person (#PCDATA)>
]>
<Root>
   <Employee>Smith,Joe C.</Employee>
</Root>

この場合、<Employee> 要素が DTD セクションで宣言されていないので、エラーが予想されます。ここで、メソッド例 WriteNodes() を使用してこのドキュメントを読み取る場合、出力は以下のようになります。

Node 1 is a(n) element named: Root
    and has no value
Node 2 is a(n) ignorablewhitespace and has no name
    with value:
 
Node 3 is a(n) error and has no name
    with value: Unknown element 'Employee' 
while processing c:/TextReader/docwdtd2.txt at line 7 offset 14
Node 4 is a(n) element named: Employee
    and has no value
Node 5 is a(n) chars and has no name
    with value: Smith,Joe C.
Node 6 is a(n) endelement named: Employee
    and has no value
Node 7 is a(n) ignorablewhitespace and has no name
    with value:
 
Node 8 is a(n) error and has no name
    with value: Element 'Employee' is not valid for content model: '(Person)' 
while processing c:/TextReader/docwdtd2.txt at line 8 offset 8
Node 9 is a(n) endelement named: Root
    and has no value

詳細は、“SAX パーサの使用法のカスタマイズ” の章の “パーサ・フラグの設定” も参照してください。

例 : ネームスペースのレポート

次のサンプルのメソッドでは、任意の XML ファイルを読み取り、それぞれの要素および属性が属するネームスペースを示します。

ClassMethod ShowNamespacesInFile(filename As %String)
{
  Set status = ##class(%XML.TextReader).ParseFile(filename,.textreader)
  
  //check status
  If $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
  
  //iterate through document, node by node
  While textreader.Read()
  {
    If (textreader.NodeType = "element")
    {
       Write !,"The element ",textreader.LocalName
       Write " is in the namespace ",textreader.NamespaceUri
       }
    If (textreader.NodeType = "attribute")
    {
       Write !,"The attribute ",textreader.LocalName
       Write " is in the namespace ",textreader.NamespaceUri
       }
     }
}

ターミナルで使用すると、このメソッドは以下のような出力を生成します。

 
The element Person is in the namespace www://www.person.com
The element Name is in the namespace www://www.person.com

次のバリエーションでは、XML 対応オブジェクトを受け取り、それをストリームに書き込んで、そのストリームを使用して同じタイプのレポートを生成しています。

ClassMethod ShowNamespacesInObject(obj)
{
  set writer=##class(%XML.Writer).%New()

  set str=##class(%GlobalCharacterStream).%New()
  set status=writer.OutputToStream(str)
  if $$$ISERR(status) {do $System.Status.DisplayError(status) quit ""}

  //write to the stream
  set status=writer.RootObject(obj)
  if $$$ISERR(status) {do $System.Status.DisplayError(status) quit }

  Set status = ##class(%XML.TextReader).ParseStream(str,.textreader)
  
  //check status
  If $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
  
  //iterate through document, node by node
  While textreader.Read()
  {
    If (textreader.NodeType = "element")
    {
       Write !,"The element ",textreader.LocalName
       Write " is in the namespace ",textreader.NamespaceUri
       }
    If (textreader.NodeType = "attribute")
    {
       Write !,"The attribute ",textreader.LocalName
       Write " is in the namespace ",textreader.NamespaceUri
       }
     }
  }
FeedbackOpens in a new tab