目次


Perl 開発者のための XML

第 3 回 高度な操作および書き込み手法

XSLT、SAX、そして SQL による文書変換の管理

Comments

コンテンツシリーズ

このコンテンツは全#シリーズのパート#です: Perl 開発者のための XML

このシリーズの続きに乞うご期待。

このコンテンツはシリーズの一部分です:Perl 開発者のための XML

このシリーズの続きに乞うご期待。

はじめに

まずは Rosie's Pet Shop のペット在庫から取り掛かりましょう。現在、このペット・ショップと Lizzie が経営するペット・ショップの合併という大幅な変更に向けて準備が進んでいるところです。調査により、それぞれの在庫が異なる XML 形式になっていることがわかりました。以前も紹介したように、Rosie の在庫はリスト 1 のようにレイアウトされている一方、Lizzie はリスト 9 に記載したまったく別のスキーマを使用しています。

2 つのスキーマには、以下のようにかなり多くの違いがあります。

  • 全体的に、Rosie は Lizzie が属性として保持しているものをサブ要素で表しています。
  • Lizzie の在庫は <item> サブ要素で構成されていますが、Rosie の文書でこれに対応するノードの名前は、ペットの種類にちなんで、<dog>, <cat>などになっています。
  • Rosie は Lizzie と違って、在庫のすべてに名前を付けています。
  • Rosie は価格、Lizze はコストを保存しています。
  • Lizzie の在庫では年齢をリストしている一方、Rosie は誕生日 (「dob」) をリストしています。
  • Lizzie には項目ごとに所在がありますが、Rosie には所在がありません。
  • Rosie にはペットのうち犬に対してだけ所有者がありますが、Lizzie には所有者はありません。

Lizzie の在庫でリストしている年齢と Rosie のヨーロッパ形式の誕生日を共通の形式に変換しますが、そのまますぐに変換するわけにはいきません。まず、年齢を現在の日付形式に変換してから、Perl が関係するこの後のステップでのように、日付を標準 YYYY-MM-DD 形式に変換することになります。

検討の末、データベース管理システム (DBMS) にデータを保管するための SQL テーブルの仕様を決めました。データベース・テーブルを作成するための SQLはリスト 6 に記載しています。これが、列が属性にマップされている Lizzie の XML データ表現にマップするには最も簡単だという考えの結果です。決定した作業手順は、まず 2 つの異なる XML ファイルを共通レイアウトに変換し、SQL データベースに保管してファイルをマージした後、データベースから共通の在庫ファイル (XML 文書) を生成するというものです。

手順の開始

連載の今までの 2 回の記事と同じく、この記事に記載したコードを実行するには、いくつかの Perl モジュールを追加する必要があります。UNIX® または Linux™ のユーザーは、cpan リポジトリーからモジュールを入手してください。Windows® のユーザーは通常、ppm を使ってモジュールを入手します (「参考文献」にリンクを記載)。該当するモジュールは以下のとおりです。

  • DBI -- リレーショナル・データベース・インターフェース
  • XML::LibXSLT -- スタイルシートの処理用

スタイルシートと DOM

Rosie の在庫を共通形式に変換するには、XSLT スタイルシート (rosie.xsl、リスト 2 を参照) を使うことにしました。この決定には必然的に、XML 文書 (リスト 1 の在庫) とスタイルシートの両方を解析し、それから XSLT を使用して文書を新規に生成するという作業が伴います。

リスト 1. Rosie の在庫
<pets>
  <cat><name>Madness</name>
    <dob>1 February 2004</dob><price>150</price></cat>
  <dog><name>Maggie</name>
    <dob>12 October 
2002</dob><price>75</price><owner>Rosie</owner></dog>
  <cat><name>Little</name>
    <dob>23 June 2006</dob><price>25</price></cat>
</pets>

ここで使用する XSLT スタイルシートは、各サブ要素を <item> 要素に変換し、サブ要素の名前として使用されていたタグを値に持つ新しい属性タイプを作成します。また、下位レベルのサブ要素はすべて属性に変換し、そのコンテンツを対応する属性の値に変換します (リスト 2 を参照)。

リスト 2. rosie.xsl スタイルシート
<xsl:stylesheet version="1.0">
  <xsl:template match="/pets">
    <xsl:element name="stock">
      <xsl:for-each select="*">
        <xsl:element name="item">
          <xsl:attribute name="type">
            <xsl:value-of select="name()"/>
          </xsl:attribute>
          <xsl:for-each select="*">
            <xsl:attribute name="{name()}">
              <xsl:apply-templates/>
            </xsl:attribute>
          </xsl:for-each> 
          <xsl:attribute name="cost">0.00</xsl:attribute>
          <xsl:attribute name="location">Rosies</xsl:attribute>
        </xsl:element>
      </xsl:for-each>
    </xsl:element><
  </xsl:template>
</xsl:stylesheet>

また、このスタイルシートを使用してコストと所在の属性も追加しています。それは、ここで追加しておけば、コストも所在も 1 行のコードで済み、後で SAX ハンドラーで追加して、もっとたくさんの作業をする可能性が出てくるよりも良いからです。

この変換を行うのは 1 度だけではないので (ここで行うほかに、次のセクションでも行います)、Perl モジュール RosieStock.pm に共通コードを書き込みます (リスト 3 を参照)。

リスト 3. RosieStock.pm (一部)
package RosieStock;
use strict;
use XML::LibXML;
use XML::LibXSLT;
use XML::LibXML::SAX::Generator;

sub new { 
    my $class = shift;
    my $parser = XML::LibXML->new;
    my $xslt   = XML::LibXSLT->new;
    my $style  = $parser->parse_file('rosie.xsl');
    my $self = { 
        PARSER      => $parser,
        STYLESHEET  => $xslt->parse_stylesheet($style),
    };
    bless $self, $class;
}
sub parseAndStyle {
    my ($self, $inFile) = @_;
    $self->{DOC}       = $self->{PARSER}->parse_file($inFile);
    $self->{STYLED}    = $self->{STYLESHEET}->transform($self->{DOC});
    return $self;
}
sub toString {
    my ($self) = shift;
    $self->{STYLESHEET}->output_string( $self->{STYLED} );
}

変換は、リスト 4 に示す Perl のスニペットで実行します。このスニペットは在庫とスタイルシートを解析し、スタイルシートを適用して結果を出力します (リスト 5)。この出力で、手を加えた結果を確認できます。

リスト 4. part3a.pl
#!/usr/bin/perl -w
use strict;
use DBI;
use RosieStock;   

my $fixRosie = RosieStock->new;
print $fixRosie->parseAndStyle('pets.xml')->toString;

ご覧のとおり、元の文書に含まれていたサブ要素は属性に変換されています。在庫の実際のコンテンツは、コストと所在の属性が追加されている以外は変わりありません (リスト 5 を参照)。

リスト 5. 変換後の Rosie の在庫 (part3a.out)
<?xml version="1.0"?>
<stock>
    <item type="cat" name="Madness" dob="1 February 2004" price="150" 
    cost="0.00" location="Rosies"/>
  <item type="dog" name="Maggie" dob="12 October 2002" price="75" 
    owner="Rosie" cost="0.00" location="Rosies"/>
  <item type="cat" name="Little" dob="23 June 2006" price="25" 
    cost="0.00" location="Rosies"/>
</stock>

SAX パイプライン

第 2 回 (「参考文献」を参照) で説明したように、ツリー解析による XSLT 変換は、XML 文書がメモリー内に収まるサイズであるか、その長さが明確でないと適用できませんが、SAX では任意のサイズと長さの XML ストリームを処理できます。ただし方法はそれだけではありません。この 2 つの手法の利点を組み合わせて、XML 文書をツリーとして解析、ナビゲート、変換し、気軽にツリーを探索して SAX パイプラインにフィードするイベントを生成することも可能です。ツリー形式の Rosie の在庫は用意できているので、早速この方法を実行できます。ツリーを解析および変換したら、SAX ハンドラーに渡してデータベースに格納させます。

DOM ツリーの探索

最初に作成する SAX パイプラインには、2 つの構成部分があります。まず、DOM ツリーを探索して SAX イベントを生成するジェネレーター、そしてこれらのイベントを収集してデータベースに書き込むハンドラーです。ジェネレーターは RosieStock パッケージに追加する 1つのメソッドで、リスト 6 に示しています。一方、既存のデータベースに含まれる PETS.STOCK テーブルに行を書き込むハンドラーは、リスト 7 に示しています。リスト 8 は、SAX パイプラインを作成して実行する Perl プログラムです。

リスト 6. RosieStock.pm (残りの部分)
sub generate {
    my ($self, $handler) = @_;
    my $generator 
        = XML::LibXML::SAX::Generator->new(Handler=>$handler);
    $generator->generate( $self->{STYLED} );
}
1;

RosieStock.pm には XML::LibXML::SAX::Generator が追加されています。このジェネレーターは DOM ツリー (このモジュールで以前に作成した、スタイル設定済みの XML 文書) を探索し、SAX イベントのストリームを生成します。これらのイベントがハンドラーに渡されます。

リスト 7. Stock2DB.pm
package Stock2DB;
use XML::SAX::Base;
@ISA = ('XML::SAX::Base');
use strict;
use DBI;
use constant TYPE0 => 0;
use constant TYPE1 => 1;
use constant TYPE2 => 2;

sub new {
    my $class = shift;
    my $self  = { COUNTER => 0, HASHTYPE => TYPE0 };
    return bless {}, $class;
}

my @months = ( 'January', 'February', 'March', 'April', 'May', 'June',
               'July', 'August', 'September', 'October', 'November', 
               'December');
sub _dobFromAge($) {    # precision is not an issue!
    my $age = shift;
    my $tob = time() - $age * ((86400) * 365.25);
    my ($day, $month, $year) = (localtime($tob))[ 3, 4, 5 ];
    $year += 1900;
    return "$day $months[$month] $year";
}
# see Perl SAX 2.1 spec for details regarding $data (hash ref)

sub _getVal($$) {
    my ($hash, $name) = @_;
    return (defined $hash->{$name}) ? ''.$hash->{$name} : '';
}
# expect attribute names to appear in hash
sub _getAttrsTYPE1($) {
    my $attrs = shift;
    return (
        _getVal($attrs, 'type'),   _getVal($attrs, 'name'),  
        _getVal($attrs, 'cost'),   _getVal($attrs, 'price'), 
        _getVal($attrs, 'dob'),    _getVal($attrs, 'location'),
        _getVal($attrs, 'age'),
    ); 
}
# expect prefixed attribute names to key secondary hash
sub _getFromSecondary ($$) {
    my ($hash, $name) = @_;
    my $value;
    my $ref = $hash->{ "{}$name" };
    if (defined $ref) {
        $value = $ref->{Value};
    }
    return $value;
}
sub _getAttrsTYPE2($) {
    my $attrs = shift;
    my ($type, $name, $cost, $price, $dob, $location, $age) = (
        _getFromSecondary ($attrs, 'type'),     
        _getFromSecondary ($attrs, 'name'),     
        _getFromSecondary ($attrs, 'cost'),     
        _getFromSecondary ($attrs, 'price'),     
        _getFromSecondary ($attrs, 'dob'),     
        _getFromSecondary ($attrs, 'location'),     
        _getFromSecondary ($attrs, 'age'),     
    ); 
    return ($type, $name, $cost, $price, $dob, $location, $age);
}
sub start_element {
    my ($self, $data) = @_;
    my $elmName = $data->{Name};
    if ($elmName eq 'item') {
        my $attrs = $data->{Attributes};
        my $hashType = $self->{HASHTYPE};
        $hashType = TYPE0 if !defined($hashType);
        if ($hashType == TYPE0) {
            my @keyList = keys %$attrs;
            my $attr0 = $keyList[0];
            if ($attr0 =~ /^{}/) {
                $hashType = TYPE2;
            } else {
                $hashType = TYPE1;
            }
            $self->{HASHTYPE} = $hashType;
            $self->{COUNTER}  = 0;
        }
        my ($type, $name, $cost, $price, $dob, $location, $age);
        if ($hashType == TYPE1) {
            ($type, $name, $cost, $price, $dob, $location, $age) = 
                _getAttrsTYPE1( $attrs );
        } else {
            ($type, $name, $cost, $price, $dob, $location, $age) = 
                _getAttrsTYPE2( $attrs );
        }
        # do any necessary fixups
        if (!defined($name) or $name eq '') {
            $name = "$type-" . $self->{COUNTER}++;
        }
        if (!defined($cost) or $cost eq '' or ($cost eq '0.00') ) { 
            $cost =  0.6 * $price;
        }
        if (!defined($price) or $price eq '') {
            $price = 1.667 * $cost;
        } 
        if (!defined($dob) or $dob eq '') {
            $dob = _dobFromAge($age);
        }

        my $insert = 
            'INSERT INTO STOCK (type, name, cost, price, dob, location) '
            . "VALUES( \"$type\",  \"$name\", \"$cost\", "
            .         "\"$price\", \"$dob\",  \"$location\" )";
            
        $self->{DBH}->do ( $insert );
    }
    $self->SUPER::start_element($data);
}
sub start_document {
    my ($self, $data) = @_;
    $self->{DBH} = DBI->connect('DBI:mysql:PETS', 'genny', 'joshsgirl')
          or die "couldn't connect to PETS: " . DBI->errstr;
    $self->SUPER::start_document($data);
}
sub end_document {
    my ($self, $data) = @_;
    $self->SUPER::end_document($data);
    $self->{DBH}->disconnect;
}
1;

このハンドラーは Stock2DB のインスタンスで、最初の SAX ハンドラーとなります。これは XML::SAX::Base を拡張し、処理対象でないイベントの処理は Stock2DB パッケージに依存します (つまり、無視します)。

この例で処理しなければならないイベントは、文書の始まりと終わり、そして要素の開始だけです。start_document で書き込み先のデータベースをオープンし、end_document でデータベースをクローズします。要素の開始では要素名を調べますが、ここで対象とするのは <item> 要素だけです。<item> 要素が見つかったら、パラメーターとして渡されたハッシュから属性を抽出し、その属性を使用して SQL INSERT ステートメントを作成します。このステートメントを DBI に渡して実行します。

Perl SAX バインディングの変更によって多少複雑な事態になっています。つまり、属性値に対して 2 通りある保管形式を扱うため、このコードではタイプ (この場合は TYPE1 または TYPE2) を検出し、そのタイプに応じて属性値を抽出するようにしています。この例の場合は、属性は名前ごとに $data->{Attributes} に保管されています。

これは、基本的に XML::LibXML::SAX::Generator パッケージが古いことが原因です。あとで最新の XML::SAX::ExpatXS を使用する際には、2 番目の属性保管方法を扱うことになります。この方法では、タイプなどの属性名を使用して {}type キーを構成し、この {}type キーで属性の詳細情報 (値、接頭辞など) を含んだ別のハッシュを指定しています。

以上がすべて統合されているのが、リスト 8 の part3b.pl です。このスクリプトは、まず空のデータベース・テーブルを作成し、次に在庫ファイル pets.xml を解析および変換します。これによって作成された DOM ツリーを探索します。SAX パイプラインの終わりはハンドラーになるので、Stock2DB のインスタンスとして作成します。このハンドラーにより、パイプラインの先頭、つまり DOM ツリーを探索するジェネレーターをインスタンス化できるようになります。スクリプトを呼び出すと、作成した空のデータベース・テーブルにツリーのコンテンツが書き込まれます。

リスト 8. part3b.pl
#!/usr/bin/perl -w
use strict;
use DBI;
use RosieStock;     
use Stock2DB;

# create a clean database table 
my $dbh = DBI->connect('DBI:mysql:PETS', 'genny', 'joshsgirl')
          or die "couldn't connect to PETS: " . DBI->errstr;

$dbh->do('USE PETS');
$dbh->do('DROP TABLE IF EXISTS PETS.STOCK');
my $create = 'CREATE TABLE STOCK (           '
    . 'id       INT NOT NULL AUTO_INCREMENT, '
    . 'type     VARCHAR(64)     NOT NULL,    '
    . 'name     VARCHAR(64),  '
    . 'cost     DECIMAL(4,2), '
    . 'price    DECIMAL(4,2)    NOT NULL,    '
    . 'dob      VARCHAR(32),  ' # should be DATE, YYYY-MM-DD
    . 'location VARCHAR(64),  ' 
    . 'PRIMARY KEY (id) )     ';

$dbh->do($create)   
    or die "can't create table PETS.STOCK: " . $dbh->errstr;
$dbh->disconnect;

my $fixRosie = RosieStock->new;
$fixRosie->parseAndStyle('pets.xml');
my $dbWriter = Stock2DB->new;
$fixRosie->generate( $dbWriter );

この時点で、データベースには Rosie の元の在庫にあった項目だけが含まれることになります。これらの項目は標準形式に変換されています。

リスト 7 のコードを注意深く見てみると、Stock2DB は欠落しているコストやゼロのコストも検索し、価格からそういったコストの値を推測して見積もっていること、同様に欠落している価格についても固定マークアップを適用することでコストからその値を計算していることがわかるはずです。

XML をデータベースに書き込む方法

次のステップは、データベースに Lizzie の在庫をロードすることです (リスト 9 を参照)。

リスト 9. Lizzie のペット・ショップ在庫
<stock>
<item type="iguana" cost="124.42" location="stockroom" age="1"/>
<item type="pig" cost="15" location="floor" age="0.5"/>
<item type="parrot" cost="700" location="cage" age="6"/>
<item type="pig" cost="117.50" location="floor" age="3.2"/>
</stock>

Stock2DB.pm (リスト 7 を参照) の仕組みを利用できるので、Lizzie の在庫をデータベースにロードするには Stock2DB のインスタンスを初期化するだけで済みます。初期化により、Stock2DB インスタンスは渡されたあらゆるものをデータベースに書き込み、続けてパーサーを起動します (リスト 10 を参照)。

リスト 10. part3c.pl
#!/usr/bin/perl -w
#use strict;
use XML::SAX::ParserFactory;
use Stock2DB;
$XML::SAX::ParserPackage = "XML::SAX::ExpatXS";

my $parser = XML::SAX::ParserFactory->parser(Handler => Stock2DB->new);
eval { $parser->parse_file('pets2.xml') };
die "can't parse Lizzie's stock file: $@"   if $@;

これで、両方の在庫ファイルがデータベースにロードされました。データベースを照会すると、結果はリスト 11 のようになります。すべてのペットに名前が付けられ、欠落していたコストと価格も計算されていることに注目してください。さらに、年齢もおおよその誕生日に変換され、すべての項目に所在がリストされるようになっています。

リスト 11. マージされたデータベース
mysql > select * from PETS.STOCK;
+----+--------+----------+--------+--------+------------------+-----------+
| id | type   | name     | cost   | price  | dob              | location  |
+----+--------+----------+--------+--------+------------------+-----------+
|  1 | cat    | Madness  |  90.00 | 150.00 | 1 February 2004  | Rosies    |
|  2 | dog    | Maggie   |  45.00 |  75.00 | 12 October 2002  | Rosies    |
|  3 | cat    | Little   |  15.00 |  25.00 | 23 June 2006     | Rosies    |
|  4 | iguana | iguana-0 | 124.42 | 207.40 | 16 November 2005 | stockroom |
|  5 | pig    | pig-1    |  15.00 |  25.00 | 18 May 2006      | floor     |
|  6 | parrot | parrot-2 | 700.00 | 999.99 | 16 November 2000 | cage      |
|  7 | pig    | pig-3    | 117.50 | 195.87 | 5 September 2003 | floor     |
+----+--------+----------+--------+--------+------------------+-----------+
7 rows in set (0.00 sec)
mysql>

データベースによる SAX パイプラインの操作

最後の目標となるのは、上記で作成したデータベースを XML 形式に再びダンプすることです。日付形式は SQL データベースにあまり適していませんが、Date::Calc を使って MySQL にふさわしい YYYY-MM-DD 形式に日付を変換するのは読者の皆さんに任せます。

SAX パイプラインを操作するには、XML::Generator::DBI を使用します。XML 文書のルート要素とサブ要素には名前を指定しなければならないことに注意してください。SQL テーブルへの保管時に、ルート要素とサブ要素の名前が必然的に失われているためです。また、XML::Generator::DBI はデフォルトで列値をサブ要素として出力します。XML 文書では列値は属性でなければならないので、AsAttributes オプションは 1 に設定してください。リスト 12 でこのジョブを実行すると、リスト 13 の XML 出力が作成されます。

リスト 12. part3d.pl
#!/usr/bin/perl -w
use strict;
use DBI;
use XML::Generator::DBI;
use XML::SAX::Writer;

my $dbh = DBI->connect('DBI:mysql:PETS', 'genny', 'joshsgirl')
          or die "couldn't connect to PETS: " . DBI->errstr;
my $select = qq ( SELECT * FROM STOCK );
my $writer = XML::SAX::Writer->new(Output => 'inventory.xml');
my $generator = XML::Generator::DBI->new(
                            dbh          => $dbh,
                            Handler      => $writer, 
                            
                );
$generator->execute($select, undef,
                           AsAttributes => 1,
                           QueryElement => undef,
                           RootElement  => 'stock',
                           RowElement   => 'item',
);
$dbh->disconnect;

リスト 13 に示す出力は整然と表示され、読みやすくなっています。ジェネレーターは属性の順序を変えてしまいますが、順序の乱れが激しい場合は (このアプリケーションでは違います)、処理ステップを追加すれば訂正できます。

リスト 13. part3d の出力: inventory.xml
<stock>
  <item cost="90.00" dob="1 February 2004" location="Rosies" 
    name="Madness" price="150.00" id="1" type="cat"/>
  <item cost="45.00" dob="12 October 2002" location="Rosies" 
    name="Maggie" price="75.00" id="2" type="dog"/>
  <item cost="15.00" dob="23 June 2006" location="Rosies" 
    name="Little" price="25.00" id="3" type="cat"/>
  <item cost="124.42" dob="16 November 2005" location="stockroom" 
    name="iguana-0" price="207.40" id="4" type="iguana"/>
  <item cost="15.00" dob="18 May 2006" location="floor" 
    name="pig-1" price="25.00" id="5" type="pig"/>
  <item cost="700.00" dob="16 November 2000" location="cage" 
    name="parrot-2" price="999.99" id="6" type="parrot"/>
  <item cost="117.50" dob="5 September 2003" location="floor" 
    name="pig-3" price="195.87" id="7" type="pig"/>
</stock>

XML::Generator::DBI のセットアップはかなり簡単でしたが、リスト 12 の Perl スクリプトを実行したところ、多数の煩わしい警告メッセージが出力されました。いくつかの修正をモジュールに追加すると、警告メッセージは出力されなくなりました。この問題は、次のリリースで修正されるはずです (この記事ではバージョン 1.0 で作業しています)。当分の間は、diff ファイルとして著者によるパッチが用意されているので利用してください。

まとめ

この連載ではまず、大抵の XML 文書の場合は単一のステップ (XML::Simple を使用) で、簡単に操作できる Perl データ構造に変換したり、Perl データ構造から XML 文書に戻せることを披露しました。

第 2 回では XML 解析用の強力なツール、DOM スタイルのツリー・パーサーおよび SAX イベント・ベース・パーサーを紹介しました。さらに、XML::SAX::Base の概要、そしてこれを使用して SAX イベントのソース、ハンドラー、シンクを作成する方法を説明しました。

この最終回では、リレーショナル・データベースを加えて連載の総仕上げとしました。まず取り上げたのは、解析ツリーを作成して変換した後、変換したツリーを探索し、データベースにフィードする SAX イベントを生成する方法です。次に SAX パイプラインを使用して 2 つ目の XML 文書を解析および変換し、1 つ目の XML 文書と同じデータベースに追加して 2 つの在庫をマージする方法を説明しました。最後のステップでは、マージされた文書を保持しているデータベースを使って別の SAX イベント・ストリームを生成し、別のパイプラインでこれをさらに変換して最終的な共通文書を作成しました。


ダウンロード可能なリソース


関連トピック

  • 本連載のこれまでの記事を読んでくさい。 第 1 回: XML::Simple を使用した、XML 文書と操作が簡単な Perl データ構造との単一ステップの変換方法を説明しています。この方法は、たいていの XML 文書に使用できます。
  • 第 2 回: XML 解析用の強力なツール、DOM ツリー・パーサーおよび SAX イベント・ベース・パーサーを紹介しています。
  • Perl での参照の使用方法に関するチュートリアル: Perl 参照とネストされたデータ構造のすべての側面に関する完全な資料です。
  • Perl developers: Fill your XML toolbox」(Parand Darugar 著、developerWorks、2001年6月): Perl を使って XML を操作するための 20 の必須ツールおよびライブラリーの概要を紹介しています。
  • Perl で DOM と XPathを用いた効果的な XML 処理」(Parand Darugar 著、developerWorks、2001年10月): DOM を効果的かつ効率的に利用する方法を説明しています。
  • High-order perl』(Mark Jason Dominus 著、2005 年): Perl での機能プログラミング手法、そして他の関数を変更および作成できる関数を作成する方法を解説した本です。
  • IBM XML 認証: XML や関連技術の IBM 認定開発者になる方法について調べてください。
  • XML Technical library: 広範な技術に関する記事とヒント、チュートリアル、標準、そして IBM レッドブックについては、developerWorks XML ゾーンを参照してください。
  • Document Object Model (DOM) 仕様: プログラムとスクリプトがコンテンツ、構造、そして文書スタイルに動的にアクセスして更新することを可能にする、プラットフォームと言語に依存しないインターフェースの詳細を調べてください。
  • Perl SAX 2.1 バインディング: Perl モジュールで使用する SAX バージョンについての資料を入手してください。
  • Perl: 最新バージョンを入手して実行してください。
  • 膨大な CPAN Perl ライブラリー (Google の検索結果 1800 万件): Comprehensive Perl Archive Network にアクセスしてください。この記事で触れたすべてのモジュールのリンクが掲載されています。
  • Windows 対応 PPM (Perl Package Manager): 一般的な Perl CPAN モジュール (Tk、DBI など) をインストール、アンインストール、アップグレード、あるいはその使用方法を管理できるツールを ActivePerl と一緒に入手してください。
  • Grant McLean の XML::Simple: 基礎 XML 解析モジュールの上位に位置する単純な API レイヤーとして XML::Simple モジュールを試してみてください。
  • XML 仕様: Extensible Markup Language (XML) の詳細を調べてください。
  • XPath 1.0: DOM ツリーをナビゲートするための言語の仕様を入手してください。
  • XSLT 1.0 仕様: XML 文書間での変換について学んでください。
  • Perl によるツリー・ベース XML のスクリプト作成」(Parand Darugar 著、developerWorks、2000年7月): Perl を使ったツリー・ベースの XML 解析を詳細に紹介しています。
  • IBM トライアル・ソフトウェア: developerWorks から直接ダウンロードできるトライアル・ソフトウェアで、次の開発プロジェクトを構築してください。

コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=XML, Web development
ArticleID=249866
ArticleTitle=Perl 開発者のための XML: 第 3 回 高度な操作および書き込み手法
publish-date=02132007