XML DOM ガイド 初心者の為の XML DOM ガイド イントロダクション 本稿は XML(eXtensible Markup Language) 形式のドキュメントからデータを受け取ろうと仕て居る Microsoft Visual Basic の開発者を対象と仕て居る 此処では XML ドキュメントから情報を取得し 其のデータを Visual Basic のソリューションに統合する方法を説明する 亦 本稿の読者は 自分自身でコードを作成出来て 最終的にはテキストファイルと成る XML ファイルの内容を自分自身で解析出来る事を前提として居る 此れは 非生産的な方法で XML の良い特長を損なう物で有る 本来 XML は データを表す為の構造化された方法なので 自分で目視して解析等をする必要は無い XML ファイルから情報を取得するには XML パーサーを使用する事を勧める XML パーサーは XML を読み込んで其の中のデータを利用可能にする非常にシンプルなソフトウェアで有る Visual Basic の開発者は XML DOM(Document Object Model) をサポートするパーサーを使用する事が出来る DOM は パーサーが公開する標準的なコマンドセットを定義して居る 此れに依り プログラムから HTML や XML ドキュメントの内容にアクセスする事が出来る DOM をサポートする XML パーサーはデータを XML ドキュメントから取り込み プログラム可能な一連のオブジェクトを通じてデータに操作する事が出来る様にする 本稿では Microsoft XML パーサー (Msxml.dll) に依る XML DOM の実装を介した XML ドキュメントへのアクセスと操作方法に付いて説明する 先に進む前に 処理前の XML ファイルを直接開いて パーサーが如何に効果的に機能するかに付いての理解を深める為の説明を行う 下記のコードは CD の項目を含む Cds.xml ファイルの内容を公開する 各項目には アーティスト タイトル トラック等の情報が含まれて居る <?xml version="1.0"?> <!DOCTYPE compactdiscs SYSTEM "cds.dtd"> <compactdiscs> <compactdisc> <artist type="individual">frank Sinatra</artist> <title numberoftracks="4">in The Wee Small Hours</title> <tracks> <track>in The Wee Small Hours</track> <track>mood Indigo</track> <track>glad To Be Unhappy</track> <track>i Get Along Without You Very Well</track> </tracks> <price>$12.99</price> </compactdisc> <compactdisc> <artist type="band">the Offspring</artist> <title numberoftracks="5">americana</title> <tracks> <track>welcome</track> <track>have You Ever</track> -1-
<track>staring At The Sun</track> <track>pretty Fly (For A White Guy)</track> </tracks> <price>$12.99</price> </compactdisc> </compactdiscs> 上記のドキュメントの 2 行目で 外部の DTD(Document Type Definition) ファイルを参照して居る DTD は レイアウトや 特定の種類の XML ドキュメントに対して予期される内容を定義して居る XML パーサーは DTD を使用してドキュメントが DTD に従って居るか何うかを判断する事が出来る DTD は パーサーがドキュメントの有効性を判断する為に使用する方法の 1 つで有る ドキュメントの有効性を判断する為に一般化しつゝ有るもう一つの方法は XML スキーマで有る 独自の 特徴有る 構文を使用する DTD に対して XML スキーマでは XML を使用してスキーマを定義する 下記のコードは Cds.xml に依り使用される Cds.dtd の内容を表示する <!ELEMENT compactdiscs (compactdisc*)> <!ELEMENT compactdisc (artist, title, tracks, price)> <!ENTITY % Type "individual band"> <!ELEMENT artist (#PCDATA)> <!ATTLIST artist type (%Type;) #REQUIRED> <!ELEMENT title (#PCDATA)> <!ATTLIST title numberoftracks CDATA #REQUIRED> <!ELEMENT tracks (track*)> <!ELEMENT price (#PCDATA)> <!ELEMENT track (#PCDATA)> 此処では DTD や XML スキーマの内容に付いては詳しく説明しない XML Schema language( 英語 ) は W3C に提出された XML-Data( 英語 ) ノートに基づいて居る DOM に付いて XML の DOM は XML ドキュメントの内容を公開するオブジェクトモデルで有る W3C の Document Object Model (DOM) Level 1 Specification では 現在 DOM が表示するプロパティ メソッド 及びイベントの種類を定義して居る Microsoft の DOM 実装は W3C 標準を完全にサポートして居り 更に追加された機能も有る 此の機能を使うと 作成するプログラムに於ける XML ファイルの操作をより簡単に行う事が出来る XML DOM の使用方法 XML DOM を使用するには XML パーサーのインスタンスを作成する 此れを可能にする為に Microsoft は Msxml.dll の中の一連の COM インターフェイスを使用して XML DOM を公開して居る Msxml.dll には XML ドキュメントで使用可能なタイプライブラリと実装コードが含まれて居る Internet Explorer で実行する VBScript 等のスクリプトクライアントを使用して居る場合は CreateObject メソッドに依り DOM を使用し Parser オブジェクトのインスタンスを作成する -2-
Set objparser = CreateObject( "Microsoft.XMLDOM" ) Active Server Page(ASP) の VBScript を使用して居る場合は Server.CreateObject を使用する Set objparser = Server.CreateObject( "Microsoft.XMLDOM" ) Visual Basic を使用して居る場合は Msxml.dll で提供される MSXML タイプライブラリへの参照を設定する事に依り DOM にアクセス出来る Visual Basic 6.0 で MSXML を使用するには 下記の操作を行う 1.[ プロジェクト ] メニューから [ 参照設定 ] ダイアログボックスを開く 2. 表示される COM オブジェクトの一覧の Microsoft XML, version 2.0 をクリックする 此の項目が表示されない場合は MSXML ライブラリが必要で有る 3. 此れで Parser オブジェクトのインスタンスを作成する事が出来る Msxml.dll を取得するには 下記の孰れかの方法で MSXML ライブラリを入手する Internet Explorer 5.0 をインストールする コンポーネントに MSXML パーサーが含まれて居る Microsoft XML Parser( 英語 ) の再配布可能バージョンをダウンロードする http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/dnarxml/html/xmlparser.asp Visual Basic プロジェクトでタイプライブラリを参照すると パーサーを使用してドキュメントを読み込み 其のデータを使用する事が出来る様に成る 何の作業して居るのかと疑問に感じた時には Visual Basic 6.0 のオブジェクトブラウザで MSXML ライブラリを開き オブジェクトモデルを調べると オブジェクトモデルが非常に豊富で有る事が解る 本稿では DOMDocument クラスと IXMLDOMNode インターフェイスを使用して XML ドキュメントにアクセスする方法を説明する ドキュメントの読み込み方法 XML ドキュメントを読み込むには 先ず最初に DOMDocument クラスのインスタンスを作成する必 -3-
要が有る 有効な参照値を取得した後 Load メソッドを使用してファイルを開く MSXML パーサーを使用すると UNC 参照を使用したネットワーク 又は URL を介してローカルディスクから XML ドキュメントを読み込む事が出来る ディスクからドキュメントを読み込むには Load メソッドを使用して下記の構文を作成する If xdoc.load("c: My Documents cds.xml") Then ドキュメントでの作業が終了すれば 必ずオブジェクト参照を解放する必要が有る MSXML パーサーでは 明示的な Close メソッドは公開されて居ない 此の為 参照先を Nothing に設定する パーサーにファイルの読込を要求すると 既定では非同期的に読み込みが行われる ドキュメントの Boolean Async プロパティを変更すると 既定の設定を変更出来る ドキュメントの内容を操作する前に ドキュメントの ReadyState プロパティを調べ ドキュメントの準備が整って居る事を確認する ReadyState プロパティは下記の 5 つの値の孰れかを返す 状態 値 Uninitialized: 読込は開始して居ない 0 Loading:Load メソッドを実行中で有る 1 Loaded:Load メソッドが完了した 2 Interactive:DOM が読み取り専用で操作可能で有る データの一部丈が解析済みで有る 3 Completed: データの読込と解析が完了し 読み取りと書き込み作業が可能で有る 4 MSXML パーサーは 読込処理のステータスを追跡する為に 大きなドキュメントの読み込み時に使用可能なイベントを公開する 此等のイベントは インターネットを介して URL から非同期的にドキュメントを読み込む場合にも役立つ URL を使用してファイルを開くには 完全な URL アドレスでファイルの場所を指定する ファイルの場所を示すアドレスの前に http:// を付ける必要が有る URL を使用してファイルを読み込む例を下記に示す xdoc.async = False If xdoc.load("http://www.develop.com/hp/brianr/cds.xml") Then -4-
ドキュメントの Async プロパティを False に設定すると ドキュメントが完全に読み込まれて処理の準備が整う迄 パーサーはコードにコントロールを返さない True に設定した場合 ドキュメントにアクセスする前に ReadyState プロパティを調べるか DOMDocument のイベントを使用して ドキュメントの準備が完了した際に通知を行うコードを設定する必要が有る エラーの対処 様々な理由に依り ドキュメントを読み込めない場合が有る 一般的な理由と仕ては Load メソッドに渡されるドキュメント名が無効で有る事等が考えられる 其の他の理由と仕ては XML ドキュメント自体が無効で有る場合等も考えられる 既定では ドキュメントに DTD 又は スキーマが特定されて居る場合 MSXML パーサーはドキュメントを孰れかに照らし合わせて確認する Load メソッドを実行する前に DOMDocument 参照オブジェクトの ValidateOnParse プロパティを設定して パーサーがドキュメントを確認しない様にも設定する事が出来る xdoc.validateonparse = False If xdoc.load("c: My Documents cds.xml") Then 開発する製品版のアプリケーションでパーサーの確認機能をオフにする事は推奨出来ない ドキュメントが正しくない為に 様々な理由でプログラムにエラーが発生する可能性が有る エラーが発生しない場合でも 無効なデータが読み込まれる可能性が有る ParseError オブジェクトにアクセスすると 種類に拘らず エラーに関する情報をパーサーに要求する事が出来る ParseError オブジェクトのプロパティを使用するには ドキュメント自体の IXMLDOMParseError インターフェイスへの参照を設定する IXMLDOMParseError インターフェイスは エラーの原因を調査する際に使用可能な 7 つのプロパティを公開する 下記の例では メッセージボックスと ParseError オブジェクトから取得可能なエラー情報を表示する If xdoc.load("c: My Documents cds.xml") Then -5-
Dim strerrtext As String Dim xpe As MSXML.IXMLDOMParseError ' ParseError オブジェクトを取得する Set xpe = xdoc.parseerror With xpe strerrtext = " 下記の XML ドキュメントの読込に失敗 :" & _ " 下記のエラーが原因で有る " & vbcrlf & _ " エラー # : " &.errorcode & ": " & xpe.reason & _ " 行 #: " &.Line & vbcrlf & _ " 行位置 : " &.linepos & vbcrlf & _ " ファイル内の位置 : " &.filepos & vbcrlf & _ " ソーステキスト : " &.srctext & vbcrlf & _ " ドキュメント URL : " &.url End With MsgBox strerrtext, vbexclamation Set xpe = Nothing ParseError オブジェクトに依り公開される情報を使用して此の情報を表示し エラーファイルに記録したり エラーを修正する事が出来る XML ドキュメントからの情報の取得 ドキュメントの読込が完了したら 此のドキュメントから情報を取得する ドキュメントオブジェクトは重要だが 殆どの場合 IXMLDOMNode インターフェイスを使用する IXMLDOMNode インターフェイスを使用して 各ノードの要素に対して読み取り / 書き込みを行う MSXML パーサーでは 現在 13 種類のノードをサポートして居る 下記の表に一覧表示されて居るのは 最も一般的なノードタイプの一部で有る DOM ノードタイプ NODE_ELEMENT NODE_ATTRIBUTE NODE_TEXT NODE_PROCESSING_INSTRUCTION NODE_DOCUMENT_TYPE 例 <artist type="band">the Offspring</artist> <artist type="band">the Offspring</artist> <artist type="band">the Offspring</artist> <?xml version="1.0"?> <!DOCTYPE compactdiscs SYSTEM "cds.dtd"> IXMLDOMNode インターフェイスに依り公開される 2 つのプロパティを通じてノードタイプにアクセスする NodeType プロパティは DOMNodeType アイテムの列挙を公開する 此の内の幾つかは上の一覧に表示されて居る 更に NodeTypeString を使用してノードタイプの文字列を取得出来る ドキュメントへの参照を取得すると ノード階層の走査を開始出来る ドキュメントへの参照から ChildNodes プロパティにアクセス出来る ChildNodes プロパティはドキュメントの総てのノードへのトップダウン形式のエントリポイントを提供する ChildNodes プロパティは Visual Basic の For/Each 構造をサポートする IXMLDOMNodeList を公開する 此の為 ChildNodes プロパティの各ノードを総て列挙する事が出来る 更に ChildNodes プロパティは存在する子ノードの数を返す Level プロパ -6-
ティを公開する ドキュメントオブジェクト丈でなく 各ノードも同様に ChildNodes プロパティを公開する 此れに依り IXMLDOMNode の HasChildNodes プロパティと共に 要素 属性 値を調査して簡単にノードの階層を走査する事が出来る 注意す可き点は ドキュメントの要素と其の要素の値との親子関係で有る 例えば CD XML ドキュメントでは 要素 <title> は 曲のタイトルを公開する <title> 要素の実際の値を取得するには NODE_TEXT タイプのノードを調べる必要が有る 目的のデータを持つノードを見つければ ParentNode プロパティを通じて属性を調査し 親ノードを確認した上でアクセス出来る ドキュメントの走査方法 XML ドキュメント内で ドキュメントオブジェクトに依り公開された一連のノードを走査する XML ドキュメントは階層形式で有る為 ドキュメント全体を走査する再帰ルーチンを 比較的簡単に作成する事が出来る LoadDocument ルーチンは XML ドキュメントを開いた後 もう一つのルーチン DisplayNode を呼び出す 此のルーチンが 実際にドキュメントを走査する LoadDocument は パラメータやインデントレベルの開始位置を指定する整数値と仕て 現在開いて居る XML ドキュメントの ChildNodes プロパティに参照を渡す Indent パラメータは コード中でドキュメントの構造体を Visual Basic のイミディエイトウィンドウに表示する際の書式を指定する DisplayNode 関数は 特に NODE_TEXT タイプのノードをドキュメントから探す 関数が NODE_TEXT タイプのノードを見付けると NodeValue プロパティを使用してノードのテキストを取得する 更に 現在のノードの ParentNode プロパティを使用して NODE_ELEMENT タイプの参照元を取得する NODE_ELEMENT タイプのノードは NodeName プロパティを公開する NodeName と NodeValue の内容が表示される HasChildNodes プロパティを調べる事に依り ノードに子ノードが存在して居る事が判明すると ドキュメントの最後に達する迄 DisplayNode が再帰的に自身を呼び出す DisplayNode ルーチンは Debug.Print を使用して Visual Basic のイミディエイトウィンドウに情報を書き込む Public Sub LoadDocument() xdoc.validateonparse = False If xdoc.load("c: My Documents sample.xml") Then DisplayNode xdoc.childnodes, 0 ' エラー情報に付いては上記の一覧を参照する End Sub -7-
Public Sub DisplayNode(ByRef Nodes As MSXML.IXMLDOMNodeList, ByVal Indent As Integer) Dim xnode As MSXML.IXMLDOMNode Indent = Indent + 2 For Each xnode In Nodes If xnode.nodetype = NODE_TEXT Then Debug.Print Space$(Indent) & xnode.parentnode.nodename & ":" & xnode.nodevalue If xnode.haschildnodes Then DisplayNode xnode.childnodes, Indent Next xnode End Sub -8-