簡単なXML読み込み

おう、オラ、メソだっちゃ。(キャラクター) つー訳で第5回、行ってみたいと思います。 が、その前に、補足&予備知識。

第3回でやったファイル読み込み。 超簡単に力技なんかでやる場合は使ったりもしますが、 実際には余り多用しません。(使わないのかよ)

何か、文章を取り込んだりとか、そんな時くらいでしょうか。 そもそも、何でファイルの内容を取り込みたいかと言うと、下記の2つの理由がダントツで多いんじゃないかと思います。

  • プログラムの設定情報を外部ファイルから読み込む
  • 定型化された表データ(CSV,xls,mdb等)を外部ファイルから取り込む

実は、この2つの用途にはそれぞれ専用の読み込み方があります。 今回は前者の「設定ファイルの読み込み」をやってみたいと思います。 「設定ファイルって?」って思うかもしれません。 まあ、どんな形式であれ、設定情報が保存されていれば設定ファイルな訳ですが、 Windowsには「標準的な設定ファイルの形式」があります。 以前までは標準的な設定ファイルの形式は.iniファイル形式でした。 これはWindowsにレジストリ*1と言う概念が生まれる前に 設定情報を各アプリケーションごとに保持する為に使用されたファイル形式です。 レジストリの使用を嫌う開発者は今でも.iniファイルを使用します。 フォルダごとコピーすれば他の環境でもそのまま設定が引き継げると言う便利な一面もあります。 が、この形式は既に過去のもので、WSHにも.iniファイルを読み込むAPIは提供されていません。では最近はどんな形式を利用するのか。 XMLを設定ファイルとして使用します。

前置きが長くなりましたので早速行ってみましょう。今回のテーマは「XMLファイルの読み込み」です。

XMLにアクセスするには、FileSystemObjectのように、 XML専用のオブジェクトを使用すると、とてもお手軽です。 XML用のヤツは、「MSXML2.Domdocument」と言います。 名前の由来は分かる人には分かるし分かんない人には全然分かんないと思いますが、 どっちにしても、これはとりあえず覚えるしかないです。 で、読み込みのサンプルを見てみましょう。

まず、読み込むXMLがこんな感じだったとします。(ファイル名:wakame.xml)

<?xml version="1.0" encoding="Shift_JIS" ?>
<school name="わかめ">
  <grade>高校</grade>
  <club name="セクシーコマンドー部">
    <members>
      <member>マサルさん</member>
      <member>フーミン</member>
      <member>マチャ彦</member>
      <member>校長</member>
      <member>キャシャリン</member>
      <member>モエモエ</member>
      <member>アフロくん</member>
    </members>
  </club>
  <club name="野球部">
    <members>
      <member>川島</member>
      <member>目立たない人々</member>
    </members>
  </club>
</school>

XMLって何ざましょ?」みたいな喋り方の人はまずいないと思いますが、 「XMLって何?」と言うような方はいるかもしれませんので、一応説明。

かなりテキトーに言うと、 「コンピュータに分かり易く、且つ、人間にもそこそこ読めるデータ形式の1つ」です。 ちゃんとしたページや解説を見たらもっと凄い事が書いてあって難しそうな感じですが、 平たく言えば単なるテキストデータです。

見れば何となく分かると思いますが、要するにHTMLみたいなタグで名前を自由に付けて、その中に値を書く。 それだけです。それ以上の何者でもありませんので、XMLと聞いたからといって引く必要は全くありません。

「コンピュータに分かり易い」とは「データに『名前』と『』が割り当てられる」と言うことです。 例えば、「野球部」と言われたときに、 人間なら「学校の部活動」だろうと大体分かりますが、コンピュータはそんな事分かるわけありません。 「キャシャリン」とかに至っては人間でも「人のあだ名」である事を認識するのは困難です。 が、<member> と、名前が最初からデータについていれば、コンピュータでも「何かのmemberである」 と言うことが分かっちゃう、っつーことです。しかもそれが<club>の下にあれば「clubのmemberである」 っつーことが分かっちゃうっつー寸法です。

これをデータを取得する時で考えてみると、例えばCSV(カンマ区切り)のデータでは、 基本的には「値」しか無い為、あだ名が2列目にあったとすると、コンピュータには、 「2列目のデータを取れ」としか命令できず、コンピュータにとってはそれが何なのかさっぱりです。 一方、XMLだと「名前」が付いているので「あだ名のデータを取れ」と言うことが出来るわけです。

まあ、あんまり実感沸かないかもしれませんが、この方が後々プログラムを見直したり、データ体型が 変更になったりした時とかに圧倒的に分かり易く、更に便利です。信じなさい、俺を。(強引)

で、メンバー一覧を出すにはこんな感じ。

Option Explicit
 
Dim FSO    'FileSystemObject
Dim objFile  'Fileオブジェクト
Dim xmlDoc    'XMLのDomDocumentオブジェクト
Dim xmlNodeList'XMLのNodeListオブジェクト
Dim xmlNode  'XMLのNodeオブジェクト
 
'XMLDOMDocument作成
Set xmlDoc = WScript.CreateObject("MSXML2.DOMDocument")
 
With xmlDoc
  'XML読み込み
  .Async = False
  .Load(WScript.Arguments(0))  '引数をファイル名として読み込み
  
  'メンバー一覧を取得
  Set xmlNodeList = .selectNodes("/school/club/members/member")
  
  'データを表示
  For Each xmlNode In xmlNodeList
    MsgBox xmlNode.text,,xmlNode.name
  Next
End With
 
Set xmlDoc = Nothing

ファイルをXMLとして読み込んで member の値のみを取得しています。 まず、最初のCreateObjectですが、XML文書そのものを表すDocumentオブジェクトを作成しています。 XMLDocumentを作る時は MSXML2.DOMDocument を指定します。 これはもうルールでこーゆーものなので、こんなもんだと思ってればOKです。

次の Load メソッドでXMLファイルを読み込んでいます。ここでは引数にXMLファイルが 渡される事を前提としちゃってます。ちなみに、ファイル名を引数に渡す場合、 エクスプローラ等で上の .vbs ファイルに対象ファイル(ここではXMLファイル)を ドラッグ&ドロップすることによって簡単に実現できます。
Loadの前にあるAsyncプロパティですが、これもまあ、Falseにするもんだと思っててくれればOKです。 実際には「XMLを非同期に読み込むかどうか」なんつーなんやら難しい設定なのですが、 それが何なのかを考える必要はあまりありません。要するにXMLから値が取れればいいんですから。 (グダグダ)

で、いよいよ一覧を取得する部分です。

Set xmlNodeList = .selectNodes("/school/club/members/member")

このselectNodesメソッドでXML文書の中から特定の値を取り出しています。 なんとなーく分かるかもしれませんが、このメソッドの引数には、 URLのように、上の要素から順番に「/」で区切って場所を指し示しています。 この書き方をXPathと言います。が、そんなの余り気にしなくていいです。 書き方だけ覚えてください。XPathについては後でもう少し詳しく説明します。 XMLの要素1つ1つの事をノード(Node)と言いますが、この処理によって 指定されたNodesをSelectしている訳です。Nodesとなっているのは、 指定されたノードは1つとは限らないからです。今回の場合も、 一番上の要素である<school>から順番にたどっていくと<member>と言うノードは それぞれの<club>で7人+2人で9つもあります。 その<member>の9つのかたまりがxmlNodeListに設定されるわけです。

で、次に1つずつ取り出して表示します。

For Each xmlNode In xmlNodeList
  MsgBox xmlNode.text,,xmlNode.name
Next

この For Each という構文は「塊から何かを1つずつ取り出す」構文です。魂じゃありません。(鬼武者) 構文的には、

For Each [取り出された1つの値] In [何かの塊]
    [取り出された値]を使って処理...
Next

と、なります。これで塊の中に入っている 「何か」の個数ぶんだけFor から Nextまでが繰り返されます。 今回の場合は、xmlNodeListと言うノードの塊を1つずつxmlNodeに取り出して、 MsgBoxで内容を表示している、と言うことです。xmlNodeListには9個のノードが 格納されていますので、MsgBoxは9回呼ばれる事になります。 MsgBoxでは値(text)と名前(name)を表示しています。 名前はノードの名称を意味しますのでここではmemberとなります。

で、次に「いや、9個もいらない。1つでいいよ」もしくは 「9個多イ!私、1個ダケ必要!多イ!!」みたいな場合、と言うか取り出す値が1つと 決まっている場合はもう少し簡単な取り出し方法があります。

Option Explicit
 
Dim FSO    'FileSystemObject
Dim objFile  'Fileオブジェクト
Dim xmlDoc    'XMLのDomDocumentオブジェクト
Dim xmlNode  'XMLのNodeオブジェクト
 
'XMLDOMDocument作成
Set xmlDoc = WScript.CreateObject("MSXML2.DOMDocument")
 
With xmlDoc
  'XML読み込み
  .Async = False
  .Load(WScript.Arguments(0))  '引数をファイル名として読み込み
  
  '学校の種類を取得
  Set xmlNode = .selectSingleNode("/school/grade")
  
  'データを表示
 MsgBox xmlNode.text,,xmlNode.name
End With
 
Set xmlDoc = Nothing

ほとんど同じですが、selectNodes が selectSingleNode に変わっています。 これで、NodeListではなくNode1つだけが取得できます。

基本的にはこれだけです。これだけで XML 内のデータが取り出せます。 楽なもんです。実は、ここで紹介している selectSingleNode、selectNode、text 等は標準的なXMLデータの操作方法にはないマイクロソフト独自の拡張メソッドです。 なので、本来は移植性を高める為に使わないほうがよいという人々も沢山いるのですが、 取れりゃいいんです。取れりゃ。(開き直り) 言語に依存しない標準的な操作方法よりも全然こっちのほうが分かり易いし、楽です。 その他の操作方法はもっとなれてきたら自分で調べてみればいいさ。(語り口調)

で、基本的にはこれだけなんですが、ノードを取得する時に使った URL みたいな XPath と言う書き方。これの書き方を幾つか紹介しておきます。

ノード(要素)ではなくノードの中に書いてある属性をアトリビュートと言いますが、 これが取り出したいとき。例えば、上のXMLで学校の名前が取り出したいときは、

   '学校の名前を取得
   Set xmlNode = .selectSingleNode("/school/@name")

となります。要するに @ が前に付くだけです。@が付くと ノードではなくアトリビュートを指すことになります。

次に、条件付き取得。例えば、メンバー全員じゃなく、野球部のメンバーのみ取り出したい時は、

'野球部メンバー一覧を取得
Set xmlNodeList = .selectNodes("/school/club[@name = '野球部']/members/member")

となります。条件を対象の後ろに [ ] で指定します。条件はIF文を書く時と同じ書き方です。 ここでは、<club>のnameアトリビュートが野球部のもののみに限定しています。 つまり、このNodeListには川島と目立たない人々の2件しか入ってきません。

ま、こんな感じでこれらを組み合わせれば大体のデータをXMLから任意に取り出せるのではないかと。

次回は、XML書き込み、かなぁ。

この記事は訳に立ちましたか?

選択肢 投票
はい 151  
いいえ 15  

  • たまーに、要望がカウントアップされております。ありがとうございます。近々何か書きます。 -- メソ 2004-12-17 (金) 22:19:17
  • とりあえず、第6回書いてみました。 -- メソ 2004-12-23 (木) 13:47:08
  • ポイントをついて分かりやすくまとまっててすごく参考になりました -- nao? 2005-12-02 (金) 11:38:35
  • ありがとうございます!そんな事初めて言われました。多分。 -- メソ 2005-12-02 (金) 16:47:53
  • XMLの扱いって調べても微妙にわかりにくかったので、超たすかりました! -- きむ? 2009-10-21 (水) 12:55:20
  • こんなに簡単にわかりやすく書いてあるページは初めてでした。ありがとうございました。 -- 2011-07-05 (火) 15:59:24

URL B I U SIZE Black Maroon Green Olive Navy Purple Teal Gray Silver Red Lime Yellow Blue Fuchsia Aqua White

*1 レジストリって何?って人は以下iniファイル説明無視してOKです(笑) いや、ホントに大丈夫です。