初心者のための XML DOM ガイド

初心者のための XML DOM ガイド

Brian Randell
DevelopMentor

October 1999
日本語版最終更新日 1999 年 12 月 20 日

概要: ここでは、Microsoft® XML パーサーでの XML DOM 実装を介した XML ドキュメントへのアクセスと操作方法について説明します。

目次

イントロダクション
DOM について
XML DOM の使用方法
ドキュメントの読み込み方法
エラーの対処
XML ドキュメントからの情報の取得
ドキュメントの走査方法
次のステップ

イントロダクション

本記事は、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>
		<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 (英語) non-ms link ノートに基づいています。

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 オブジェクトのインスタンスを作成します。

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 オブジェクトのインスタンスを作成することができます。

    Dim xDoc As MSXML.DOMDocument
    Set xDoc = New MSXML.DOMDocument

Msxml.dll を取得するには、次のいずれかの方法で MSXML ライブラリを入手します。

  • Internet Explorer 5.0 をインストールする - コンポーネントに MSXML パーサーが含まれています。
  • Microsoft XML Parser の再配布可能バージョンをダウンロードする。

Visual Basic プロジェクトでタイプ ライブラリを参照すると、パーサーを使用してドキュメントを読み込み、そのデータを使用することができます。

"私は何の作業しているのか ?" と疑問に思われることでしょう。 Visual Basic 6.0 のオブジェクト ブラウザで MSXML ライブラリを開き、オブジェクト モデルを調べると、オブジェクト モデルが非常に豊富であることがわかります。本記事では、DOMDocument クラスと IXMLDOMNode インターフェイスを使用して XML ドキュメントにアクセスする方法を説明します。

図 1. MSXML パーサー オブジェクト モデル

ドキュメントの読み込み方法

XML ドキュメントを読み込むには、まず最初に DOMDocument クラスのインスタンスを作成する必要があります。

Dim xDoc As MSXML.DOMDocument
Set xDoc = New MSXML.DOMDocument

有効な参照値を取得したあと、Load メソッドを使用してファイルを開きます。MSXML パーサーを使用すると、UNC 参照を使用したネットワークまたは URL を介してローカル ディスクから XML ドキュメントを読み込むことができます。

ディスクからドキュメントを読み込むには、Load メソッドを使用して次の構文を作成します。

If xDoc.Load("C:\My Documents\cds.xml") Then
	' ドキュメントの読み込みに成功しました。
	' 目的の作業を行います。
Else
	' ドキュメントに読み込みに失敗しました。
End If

ドキュメントでの作業が終了したら、きちんとオブジェクト参照を解放する必要があります。MSXML パーサーでは、明示的な Close メソッドは公開されていません。このため、参照先を Nothing に設定します。

Set xDoc = 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
	' ドキュメントの読み込みに成功しました。
	' 目的の作業を行います。
Else
	' ドキュメントに読み込みに失敗しました。
End If

ドキュメントの Async プロパティを False に設定すると、ドキュメントが完全に読み込まれて処理の準備が整うまで、パーサーはコードにコントロールを返しません。 True に設定した場合、ドキュメントにアクセスする前に ReadyState プロパティを調べるか、DOMDocument のイベントを使用して、ドキュメントの準備が完了した際に通知を行うコードを設定する必要があります。

エラーの対処

さまざまな理由により、ドキュメントを読み込めない場合があります。一般的な理由としては、Load メソッドに渡されるドキュメント名が無効であることなどが考えられます。そのほかの理由としては、XML ドキュメント自体が無効である場合なども考えられます。

既定では、ドキュメントに DTD またはスキーマが特定されている場合、MSXML パーサーはドキュメントをいずれかに照らし合わせて確認します。Load メソッドを実行する前に、DOMDocument 参照オブジェクトの ValidateOnParse プロパティを設定して、パーサーがドキュメントを確認しないようにも設定できます。

	Dim xDoc As MSXML.DOMDocument
	Set xDoc = New MSXML.DOMDocument
xDoc.validateOnParse = False
If xDoc.Load("C:\My Documents\cds.xml") Then
	' ドキュメントの読み込みに成功しました。
	' 目的の作業を行います。
Else
	' ドキュメントに読み込みに失敗しました。
End If

あなたが開発する製品版のアプリケーションでパーサーの確認機能をオフにすることはお勧めしません。ドキュメントが正しくないために、さまざまな理由でプログラムにエラーが発生する可能性があります。エラーが発生しない場合でも、無効なデータが読み込まれる可能性があります。

ParseError オブジェクトにアクセスすると、種類にかかわらず、エラーに関する情報をパーサーに要求することができます。ParseError オブジェクトのプロパティを使用するには、ドキュメント自体の IXMLDOMParseError インターフェイスへの参照を設定します。IXMLDOMParseError インターフェイスは、エラーの原因を調査する際に使用可能な 7 つのプロパティを公開します。

次の例では、メッセージ ボックスと ParseError オブジェクトから取得可能なエラー情報を表示します。

	Dim xDoc As MSXML.DOMDocument
	Set xDoc = New MSXML.DOMDocument
If xDoc.Load("C:\My Documents\cds.xml") Then
	' ドキュメントの読み込みに成功しました。
	' 目的の作業を行います。
Else
	' ドキュメントに読み込みに失敗しました。
	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
End If

Set xPE = Nothing

ParseError オブジェクトにより公開される情報を使用してこの情報を表示し、エラー ファイルに記録したり、エラーを修正することができます。

XML ドキュメントからの情報の取得

ドキュメントの読み込みが完了したら、このドキュメントから情報を取得します。ドキュメント オブジェクトは重要ですが、ほとんどの場合、IXMLDOMNodeインターフェイスを使用します。IXMLDOMNode インターフェイスを使用して、各ノードの要素に対して読み取り/書き込みを行います。MSXML パーサーでは、現在 13 種類のノードをサポートしています。次の表に一覧表示されているのは、最も一般的なノード タイプの一部です。

DOM ノード タイプ
NODE_ELEMENT <artist type="band">The Offspring</artist>
NODE_ATTRIBUTE <artist type="band">The Offspring</artist>
NODE_TEXT <artist type="band">The Offspring</artist>
NODE_PROCESSING_INSTRUCTION <?xml version="1.0"?>
NODE_DOCUMENT_TYPE <!DOCTYPE compactdiscs SYSTEM "cds.dtd">

IXMLDOMNode インターフェイスによって公開される 2 つのプロパティを通じてノード タイプにアクセスします。NodeType プロパティは DOMNodeType アイテムの列挙を公開します。このうちのいくつかは上の一覧に表示されています。さらに、NodeTypeString を使用してノード タイプの文字列を取得できます。

ドキュメントへの参照を取得すると、ノード階層の走査を開始できます。ドキュメントへの参照から ChildNodes プロパティにアクセスできます。ChildNodes プロパティはドキュメントのすべてのノードへのトップダウン形式のエントリ ポイントを提供します。ChildNodes プロパティは、Visual Basic の For/Each 構造をサポートする IXMLDOMNodeList を公開します。このため、ChildNodes プロパティの各ノードをすべて列挙することができます。さらに、ChildNodes プロパティは存在する子ノードの数を返す Level プロパティを公開します。

ドキュメント オブジェクトだけでなく、各ノードも同様に ChildNodes プロパティを公開します。これにより、IXMLDOMNodeHasChildNodes プロパティと共に、要素、属性、値を調査して簡単にノードの階層を走査することができます。

注意すべき点は、ドキュメントの要素とその要素の値との親子関係です。たとえば、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 プロパティを公開します。NodeNameNodeValue の内容が表示されます。

HasChildNodes プロパティを調べることによって、ノードに子ノードが存在していることが判明すると、ドキュメントの最後に達するまで DisplayNode が再帰的に自身を呼び出します。

DisplayNode ルーチンは、Debug.Print を使用して Visual Basic の [イミディエイト] ウィンドウに情報を書き込みます。

Public Sub LoadDocument()
Dim xDoc As MSXML.DOMDocument
Set xDoc = New MSXML.DOMDocument
xDoc.validateOnParse = False
If xDoc.Load("C:\My Documents\sample.xml") Then
	' ドキュメントの読み込みに成功しました。
	' 目的の作業を行います。
	DisplayNode xDoc.childNodes, 0
Else
	' ドキュメントに読み込みに失敗しました。
	' エラー情報については、上記の一覧を参照してください。
End If
End Sub

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
		End If

		If xNode.hasChildNodes Then
			DisplayNode xNode.childNodes, Indent
		End If
	Next xNode
End Sub

DisplayNode は、HasChildNodes プロパティを使用して、再帰呼び出しを行うかどうかを判断します。ノードの Level プロパティを使用して、0 より大きな値をチェックすることもできます。

次のステップ

この記事は最初の第一歩にすぎません。この段階で、XML と MSXML パーサーの知識を深め、広げる準備ができました。読者の方は、各ノードの要素の値を更新したり、ドキュメント内の検索、独自のドキュメントの作成などをさまざまな作業が行えます。さらに詳しい例や、記事、ダウンロードについては、MSDN Online XML Developer Center をご覧ください。