PerlSAXによるXML文書処理

[1] 以下で使用するモジュール

[2] モジュールのインストール

通常の方法でインストールできますが、ActiveStatePerl に XML::SAX::Writer をインストールする作業だけはうまく行かないようなので、その場合は次の処置に従います。

XML::SAX::Writer のインストールがうまく行かないのは use している Text::Iconv のインストールが難しいからです。筆者はいろいろ試しましたが、どれも成功しませんでした。

しかし XML::SAX::Writer のソースWriter.pm をちょっと読めば Text::Iconv の use はかならずしも必要でないことが分かります。 とくにXMLの文字コードが入力・出力共 utf-8 の場合には Text::Iconv によるコード変換は必要ではありません。

そこで Writer.pm を次のように修正します。

まず


use Text::Iconv             qw();

をコメントして


# use Text::Iconv             qw();

とします。

次に


sub setConverter {
    my $self = shift;

    if (lc($self->{EncodeFrom}) ne lc($self->{EncodeTo})) {
        $self->{Encoder} = Text::Iconv->new($self->{EncodeFrom}, $self->{EncodeTo});
    }
    else {
        $self->{Encoder} = XML::SAX::Writer::NullConverter->new;
    }
    return $self;
}


sub setConverter {
    my $self = shift;

    $self->{Encoder} = XML::SAX::Writer::NullConverter->new;
    return $self;
}

のように書き換えます。 if 文の条件が常に偽になるように書き換えても同じでしょう。

本来は別名(例えば MyWriter.pm)で保存して使用すべきですが、ここではその過程を省略します。

あとは通常のとおり

  1. make
  2. make test
  3. make install

の一連の作業でインストールが完了します。

[3] 使用例

以下のすべての例においてXMLパーサには XML::SAX::Expat を使用します。

まずは簡単な例 (sample1.pl) から。この例ではSAX2イベントのハンドラーに、インラインパッケージ(スクリプト内に書かれたパッケージ) を使用します。

Test という名前のパッケージがそれです。

Test の仕事はイベントがあったときにその情報を標準出力に出すことです。


#---------------------------------------------------
#
# Description: A handler to SAX events
#    generated by XML::SAX::Expat.
#
# Usage: sample1.pl <xml-file-name(URI)>
#
#---------------------------------------------------
use strict;

use XML::SAX::Expat;

# file 名をコマンドラインから得る
my $file = shift;

my $h = Test->new();

my $p = XML::SAX::Expat->new(
                             Handler => $h,
                             );

$p->parse_uri($file);


package Test;

sub new {
    my $class = shift;
    my $self = {
    };
    return bless $self, $class;
}

sub start_document {
    my $self = shift;
    print "Document starts.\n\n";
}

sub end_document {
    my $self = shift;
    print "Document ends.\n";
}

sub start_element {
    my $self = shift;
    my $data = shift;

    print "Element starts...\n";
    print "  Name: $data->{Name}\n";
    print "  NS_URI: $data->{NamespaceURI}\n";
    print "  Prefix: $data->{Prefix}\n";
    print "  LC_Name: $data->{LocalName}\n";

    my $attr = $data->{Attributes};

    print "  Attributes:\n";
    foreach my $key (keys %$attr){
        my $prop = $attr->{$key};
        print "    Name:     $prop->{Name}\n";
        print "    Value:    $prop->{Value}\n";
        print "    NS_URI:   $prop->{NamespaceURI}\n";
        print "    Prefix:   $prop->{Prefix}\n";
        print "    LC_Name:  $prop->{LocalName}\n";
        print "\n";
    }
    print "\n";

}


sub end_element {
    my $self = shift;
    my $data = shift;

    print "Element ends...\n";
    print "  Name: $data->{Name}\n";
    print "  NS_URI: $data->{NamespaceURI}\n";
    print "  Prefix: $data->{Prefix}\n";
    print "  LC_Name: $data->{LocalName}\n";

    print "\n";
}

sub characters {
    my $self = shift;
    my $data = shift;
    my $cdata = $data->{Data};
    if($cdata eq "\n"){
        $cdata = '\n';
    }

    print "Character Data starts...\n";
    print "$cdata\n";
    print "Character Data ends.\n";

    print "\n";
}


sub ignorable_whitespace{
    my $self = shift;
    my $data = shift;
    my $cdata = $data->{Data};

    print "Ignorable whitespace starts...\n";
    print "$cdata\n";
    print "Ignorable whitespace ends.\n";

    print "\n";
}


sub comment {
    my $self = shift;
    my $data = shift;

    print "Comment starts...\n";
    print "$data->{Data}\n";
    print "Comment ends.\n";

    print "\n";
}

sub processing_instruction {
    my $self = shift;
    my $data = shift;

    print "PI starts...\n";
    print "  Target: $data->{Target}\n";
    print "  Data:   $data->{Data}\n";
    print "PI ends.\n";

    print "\n";
}

任意のXMLファイル(foo.xml とします)を sample1.pl と同じディレクトリに置いて、下のコマンドを実行してください。


$ perl sample1.pl foo.xml

[4] XML::SAX::Writer を使用する

(未完)