XML データの中からある特定のデータだけを抽出するとしたら、どんな実装になるでしょう。


<xml>

<body>

<rows>

<row name='foo' value='bar'/>

<row name='hoge' value='fuga'/>

</rows>

</body>

</xml>


たとえば上のXMLデータの中からrowタグのnameとvalueというアトリビュートを抽出したいとします。


すぐに思いつくのはDOM を使った実装でしょうか…


VBAでサンプルを書いてみましょう。


あらかじめ参照設定でMicrosoft XMLを選択しておき、標準モジュールでマクロを実装します。



Const sampleXML As String = "<xml><body><rows><row name='foo' value='bar'/><row name='hoge' value='fuga'/></rows></body></xml>"


Sub RunDOMSample()


Dim doc As New DOMDocument

Dim bodyTag As IXMLDOMElement

Dim rowsTag As IXMLDOMElement

Dim rowTag As IXMLDOMElement


Debug.Print "using DOM"


doc.loadXML sampleXML

Debug.Assert (False = doc.parseError)


For Each bodyTag In doc.documentElement.getElementsByTagName("body")

For Each rowsTag In bodyTag.getElementsByTagName("rows")

For Each rowTag In rowsTag.getElementsByTagName("row")

Debug.Print _

rowTag.getAttribute("name"), rowTag.getAttribute("value")

Next

Next

Next


End Sub



DOMを使うと親から子、子から孫ノードへと検索していく必要があります。検索ロジックを自分で書かなければならないのが少し面倒です。。。


では、SAX を使うとどうなるでしょうか?


SAXを使う場合、IVBSAXContentHandlerインターフェースを実装したクラスを作る必要があります。クラス名を適当にSamleXMLHandlerとでもしておきましょう。



' SamleXMLHandler クラス

Implements IVBSAXContentHandler

...

Private Sub IVBSAXContentHandler_startElement( _

strNamespaceURI As String, strLocalName As String, strQName As String, _

ByVal oAttributes As MSXML2.IVBSAXAttributes)


If "row" = strQName Then

Debug.Print _

oAttributes.getValueFromQName("name"), _

oAttributes.getValueFromQName("value")

End If


End Sub

...



IVBSAXContentHandlerインターフェースのすべてのメソッドを実装する必要があるのですが、不要なメソッドは何もしない実装にしておき、startElementメソッドだけ実際の処理を書きます。


標準モジュールのマクロの実装はこんな感じになるでしょう。



Sub RunSAXSample()


Dim parser As New SAXXMLReader


Debug.Print "using SAX"


Set parser.contentHandler = New SamleXMLHandler

parser.Parse sampleXML


End Sub



ずいぶんとシンプルな実装です♪


XMLのデータ構造や処理内容によってはDOMよりSAXを使った方がシンプルな実装になるということです。もちろん、DOMを使った方が便利な場合も多いでしょう。


DOMにくらべるとSAXの方は資料も使用例も少ないような気がしたのでこんな記事を書いてみました。


それぞれ、メリット・デメリットがあるのでよく吟味して選択するといいでしょう♪