XML用ライブラリ,XML::ParserとMS XML Parser2.0を使ってみる XMLパーサーをPerl,VisualBasicから使うあれから,XMLについて勉強を進めてみました.
Unicodeまず,日本語の文字化けの件について. これは,Microsoft XMLパーサの仕様ということになりますが, 日本語については,Unicode形式で取り扱うことになるようです. つまり,この内容をメモ帳に貼り付けて,<?xml version="1.0"?> <albums> <album> <band>AION</band> <title>Aionism</title> <comment></comment> </album> <album> <band>ALCATRAZZ</band> <title>Alcatrazz</title> <comment>Yngwieのギターが速いぞ</comment> </album> <album> <band>AMORPHIS</band> <title>Elegy</title> <comment></comment> </album> </albums> メモ帳で「ファイルを名前を付けて保存」 とし,「Unicodeで保存する」にチェックを入れて保存します. (WindowsNTではできますが,Win95, 98でできるかどうかはわかりません)
![]() これで,Internet Explorer 5.0で日本語が正しく表示されるようになります.
![]() また,XMLファイル内で明示的にエンコーディングを指定するには,先頭行を下記のように記述すればOKです.
<?xml version="1.0" encoding="UTF-16"?>
で,Microsoft XMLパーサ以外を使った場合にどうなるかですが,
とりあえず環境が手に入ったということで,
Perl for Win32の XML::Parser モジュールを使ってみました.
すると,これも同じで,Unicodeで用意しておく必要がありました. $p = new XML::Parser( ErrorContext => 2, Style => 'Tree', ProtocolEncoding => 'UTF-16');
補足
XML::ParserXML::Parser とは,PerlでXMLファイルを扱うための汎用ライブラリです.今回,XML::Parserを使ってPerl for Win32で苦心惨憺で作ったアルバム情報抽出プログラムを,載せてみます. 全然Perlらしくないプログラムだとは思いますが,お目こぼしあれ. use XML::Parser; $html2 = <<EOF; <albums> <album> <band>AION</band> <title>Aionism</title> <comment></comment> </album> <album> <band>ALCATRAZZ</band> <title>Alcatrazz</title> <comment>Yngwie</comment> </album> <album> <band>AMORPHIS</band> <title>Elegy</title> <comment></comment> </album> </albums> EOF $p = new XML::Parser( ErrorContext => 2, Style => 'Tree', ProtocolEncoding => 'UTF-16'); $html2 =~ s/\n//g; $r_tree = $p->parse($html2); @albums = getAlbums( $r_tree); open(OUTFILE, '>b.txt'); print OUTFILE $albums[2]{comment}; close(OUTFILE); sub getAlbums { my ($r_parsedTree) = @_; my ($albumNo, $elmNo, $r_albumCont); my (@rslt); my (%rsltWork); $albumNo = 1; while ( defined( $r_parsedTree->[1][$albumNo*2-1])) { if ( $r_parsedTree->[1][$albumNo*2-1] eq 'album') { $r_albumCont = $r_parsedTree->[1][$albumNo*2]; $elmNo = 1; while ( defined( $r_albumCont->[($elmNo-1)*2+1]) ) { $elmName = $r_albumCont->[($elmNo-1)*2+1]; if ( defined( $r_albumCont->[($elmNo-1)*2+2][2]) ) { $rsltWork{$elmName} = $r_albumCont->[($elmNo-1)*2+2][2]; } $elmNo++; } $rslt[$albumNo] = { %rsltWork}; # 無名ハッシュ化 $albumNo++; } } return (@rslt); } XML文書中の改行の考え方で苦労しました.結局このプログラムでは, parseをかける前に改行を除去しています.なんか根本的に考えかたがおかしいのだろうか. 関数 getAlbums はハッシュの配列を返します.例えば1つめのアルバムの,commentは, @albums = getAlbums( $r_tree); print $albums[0]{comment}; 種をあかすと,Treeスタイルでparseすることによって取得できる木構造を, こんな感じで図解して,配列の添え字を考えています. [albums, [{}, album, [{}, band, [{}, 0, AION], title, [{}, 0, Aionism], comment, [{} ] ] album, [{}, band, [{}, 0, ALCATRAZZ], title, [{}, 0, Alcatrazz], comment, [{}, 0, Yngwie] ] ] ] [albums, [{}, 0, \n, album, [{}, 0, \n, band, [{}, 0, AION], 0, \n, title, [{}, 0, Aionism], 0, \n, comment, [{} ] ] 0, \n, album, [{}, 0, \n, band, [{}, 0, ALCATRAZZ], 0, \n, title, [{}, 0, Alcatrazz], 0, \n, comment, [{}, 0, Yngwie] ] ] ] まあとにかく,Perlで木構造を扱うのは私には難しい... 慣れれば良いのでしょうけどねえ
Microsoft XML Parser
他にフリーで利用できるXMLパーサとして,Microsoft XML Parserがあります.
ちなみに,Microsoft XML Parser 2.0は,
から xmlredist.exe としてダウンロード可能です. ただし,インストールする環境には Internet Explorer 4.01SP1以上が必要です. いわゆるCOMサーバですので,NewなりCreateObject()なり行って使うことになります.
補足 これを使った場合,Visual Basicに慣れている人なら, かなり簡単にXMLファイルの木構造を操作することができます. コレクション操作になるわけです. Visual Basicを起動して,「Microsoft XML Parser 2.0」を参照設定すると, 下図のようなオブジェクトが使えるようになります.
![]() VBの場合,Unicodeが簡単に扱えるのも強みかなあ... VB6+MSXMLParser2.0で同じようなプログラムを書いてみました. Private Sub txtShow_Click() Dim xd As MSXML.DOMDocument Dim xdnAlbum As MSXML.IXMLDOMNode Dim blnSuccess As Boolean Dim lngAlbumNo As Long Dim colWork As Collection Set xd = CreateObject("Microsoft.XMLDOM") blnSuccess = xd.Load("F:\kamoi\work\XML\album.xml") If Not blnSuccess Then MsgBox "Can't load xml" Exit Sub End If lngAlbumNo = 1 ' レコード抽出 Set xdnAlbum = xd.childNodes(1).childNodes(lngAlbumNo - 1) ' レコード構成要素抽出 Set colWork = getNodeTextCollection(xdnAlbum) With Me .txtBand.Text = colWork("band") .txtTitle.Text = colWork("title") .txtContents.Text = colWork("comment") End With Set colWork = Nothing End Sub
Private Function getNodeTextCollection( _ ByRef rxdnPar As MSXML.IXMLDOMNode) As Collection Dim xdnWork As MSXML.IXMLDOMNode Dim colRslt As New Collection Dim strNodeName As String Dim vntNodeText As Variant For Each xdnWork In rxdnPar.childNodes strNodeName = xdnWork.nodeName vntNodeText = xdnWork.Text colRslt.Add vntNodeText, strNodeName Next xdnWork Set getNodeTextCollection = colRslt End Function |