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の方は資料も使用例も少ないような気がしたのでこんな記事を書いてみました。
それぞれ、メリット・デメリットがあるのでよく吟味して選択するといいでしょう♪