PHPマニュアル より。。。注意: この拡張は実験的なものではありません。しかしながら、PHP 5 では決してリリースされないでしょう。また、PHP 4 でのみ配布されます。 もし PHP 5 でDOM XML をサポートする必要がある場合、 DOM 拡張を使用することができます。 この domxml 拡張は DOM 拡張と互換性はありません。
PHPでもDOM XML関数を使ってXMLファイルの操作を行うことができますが、ノードだ要素だ属性だ、なんてコーディングが結構面倒ですよね。Javaの場合、以前からRelaxer(RELAXで定義されたXMLモデルに従ったXMLドキュメントを操作するためのJavaクラスを自動生成するプログラム)を使ってアクセスクラスを自動生成し、それを使ってXMLにアクセスしていますが、コーディングの際に「XMLを操作している」という意識を持つ必要がほどんどない(メソッド「get[要素名]やget[属性名]」で取得できる)ので、非常に重宝しています。

やっぱり、PHPでもこんなのがあったら便利だよなぁ。。。ということで、以前作成したサンプルを元に、「PHP4.3.0用XMLアクセスクラスを自動生成するプログラム」を作り始めてみました。とりあえず第一弾として「既存のXMLを読み込み、それにアクセスするクラスを自動生成する」クラスです。

まず、説明に先立って、開発と確認の環境ですが、以下の通りです。

Vine Linux 2.1.5(ftp版)
Apache 1.3.24(ソースからインストール)
PHP4.3.0dev(2002/05/31にPHP本家のcvsからソースを取得&インストール)
libxml2-2.4.21(ソースからインストール)
さていきなり本題ですが、「どんなXMLからどんなPHPクラスができるか?」ですが、以下のようなXMLドキュメントを考えてみます。

●XMLドキュメント
<?xml version="1.0"?>
<article attr1="php" attr2="domxml">
  <subject>PHP関連書籍</subject>
  <book>
    <title>PHP4徹底攻略</title>
    <isbn>ISBN4-7973-1392-7</isbn>
  </book>
  <book>
    <title>Dynamic Webサイト構築入門 PHP編</title>
    <isbn>ISBN-4898142818</isbn>
  </book>
  <book>
    <title>Oracle8iとPHPで作るWebデータベースfor Miracle Linux</title>
    <isbn>ISBN4871938670</isbn>
  </book>
  <book>
    <title>PHPパーフェクトリファレンス</title>
    <isbn>ISBN-4894714027</isbn>
  </book>
</article>
  このXMLドキュメントから作成されるクラスは、XMLドキュメントに含まれる要素(タグ)毎のクラス(以下の5つ)になります。

Article
Book
Isbn
Subject
Title
例として、ArticleクラスとTitleクラスのPHPソースは、以下のような感じになります。

●Article.phl

<?php
require_once("Subject.phl");
require_once("Book.phl");
class Article
{
    var $obj_;
    function Article($obj, $mode = "file")
    {
        $mode = strtolower($mode);
        if ($mode == "file") {
            $dom = domxml_open_file($obj);
            $this->obj_ = $dom->document_element();
        }
        else if ($mode == "string") {
            $dom = domxml_open_mem(mb_convert_encoding($obj, "utf-8", "auto"));
            $this->obj_ = $dom->document_element();
        }
        else if ($mode == "obj") {
            $this->obj_ = $obj;
        }
        else {
            die("not supported mode [$mode] !");
        }
    }

    function getAttr1() { return $this->obj_->get_attribute("attr1"); }
    function getAttr2() { return $this->obj_->get_attribute("attr2"); }
    function getSubject()
    {
        $ret = array();
        $elements = $this->obj_->get_elements_by_tagname("subject");
        for ($i = 0; $i < count($elements); $i++) {
            array_push($ret, new Subject($elements[$i], "obj"));
        }
        if (count($ret) == 1) {
            $ret = $ret[0];
        }
        return $ret;
    }

    function getBook()
    {
        $ret = array();
        $elements = $this->obj_->get_elements_by_tagname("book");
        for ($i = 0; $i < count($elements); $i++) {
            array_push($ret, new Book($elements[$i], "obj"));
        }
        if (count($ret) == 1) {
            $ret = $ret[0];
        }
        return $ret;
    }

    function getContent() { return mb_convert_encoding($this->obj_->get_content(), mb_internal_encoding(), "auto"); }
}
?>

●Title.phl

<?php
class Title
{
    var $obj_;
    function Title($obj, $mode = "file")
    {
        $mode = strtolower($mode);
        if ($mode == "file") {
            $dom = domxml_open_file($obj);
            $this->obj_ = $dom->document_element();
        }
        else if ($mode == "string") {
            $dom = domxml_open_mem(mb_convert_encoding($obj, "utf-8", "auto"));
            $this->obj_ = $dom->document_element();
        }
        else if ($mode == "obj") {
            $this->obj_ = $obj;
        }
        else {
            die("not supported mode [$mode] !");
        }
    }

    function getContent() { return mb_convert_encoding($this->obj_->get_content(), mb_internal_encoding(), "auto"); }
}
?>

何となく分かるでしょうか?作成されるクラスでは、

メソッド「get[要素名]」で子要素オブジェクトを返す。子要素が複数ある場合は、子要素オブジェクトの配列として返す
メソッド「get[属性名]」で属性値を返す
メソッド「getContent」でテキストを返す
必要な別クラスファイルは、自動的にrequire_onceされる
となっています。

また、これら自動生成されたクラスを使ったサンプルは、以下のようになります。内容は、各要素の属性?テキストを順に一覧表示するものです。ここでは、DOM XML関数を一切使用していない&要素?属性の区別がなく全てgetXxxだけででアクセスできていることが分かると思います。

●test.php

<?php
require_once("phl/Article.phl");
?>
<?php
function doIt($root)
{
    echo $root->getAttr1() . "<br/>";
    echo $root->getAttr2() . "<br/>";
    $subj = $root->getSubject();
    echo $subj->getContent() . "<br/>";
    $books = $root->getBook();
    for ($i = 0; $i < count($books); $i++) {
        $title = $books[$i]->getTitle();
        echo $title->getContent()."<br/>";
        $isbn = $books[$i]->getIsbn();
        echo $isbn->getContent()."<br/>";
    }
}

    /**
     * main
     */
    unset($root);
    $root = new Article("domxml.xml");
    doIt($root);
    $root = null;
?>

●出力結果
phpdomxmlPHP関連書籍PHP4徹底攻略ISBN4-7973-1392-7Dynamic Webサイト構築入門 PHP編ISBN-4898142818Oracle8iとPHPで作るWebデータベースfor Miracle LinuxISBN4871938670PHPパーフェクトリファレンスISBN-4894714027
  自動生成プログラムの方ですが、上記XMLファイルとテストスクリプトを含めたアーカイブをダウンロードできるようにしてありますので、このページの一番上にあるリンクからダウンロードしてください。

使い方(?)の簡単な説明ですが、以下のようにDOM2PHPクラスにXMLファイル名を指定してインスタンス化し、executeメソッドを呼ぶだけで直下のphlディレクトリにファイルが作成されます。もちろん、Apacheの実行User/Groupでファイルを作成できるよう、phlディレクトリへのpermissionの設定が必要です。

●DomCodeGen.php

<?php
ini_set("include_path", "../../");
require_once "jp/ne/hi_ho/pat/dimension/xml/dom/DOM2PHP.phl";
?>
<?php
    if (!isset($_GET["xml"])) {
        die("no parameter 'xml' !!");
    }
    $d2p = new DOM2PHP($_GET["xml"]);
    $d2p->execute();
?>