Do You PHP?    
Search Engine Optimization  php5 powerd  Valid XHTML 1.0!  Valid CSS!  このサイトのはてなブックマーク数 



last updated
2005/05/25

counter hits
since 1999/11/06


PHP4.3.0でのXMLアクセスクラスの自動生成 - 目指せ(!?)Relaxer

alertここにある情報はかなり古くなっており、正しくなくなっている可能性があります。掲載しているサンプルコードiなどは、最新のPHPでは動作しない、もしくは、別途設定・調整が必要になるかも知れません。情報を鵜呑みにせず、あなたの手を動かして、あなたの目で確認してください。

zip形式 tgz形式

memo[2004/01/30] PHP5からSimpleXML関数が追加されますが、こちらもXMLをオブジェクトとして扱える関数が揃っています

alertPHPマニュアル より。。。注意: この拡張は実験的なものではありません。しかしながら、PHP 5 では決してリリースされないでしょう。また、PHP 4 でのみ配布されます。 もし PHP 5 でDOM XML をサポートする必要がある場合、 DOM 拡張を使用することができます。 この domxml 拡張は DOM 拡張と互換性はありません。

PHPでもDOM XML関数を使ってXMLファイルの操作を行うことができますが、ノードだ要素だ属性だ、なんてコーディングが結構面倒ですよね。Javaの場合、以前からRelaxerRELAXで定義された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;
?>

●出力結果
php
domxml
PHP関連書籍
PHP4徹底攻略
ISBN4-7973-1392-7
Dynamic Webサイト構築入門 PHP編
ISBN-4898142818
Oracle8iとPHPで作るWebデータベースfor Miracle Linux
ISBN4871938670
PHPパーフェクトリファレンス
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();
?>

現状ではXMLデータ(文字列)を直接DOM2PHPクラスに渡す場合、UTF-8にする必要があります。また、「とりあえず動く」レベルなものなので、あちこちバグがあるかも知れませんが、どうでしょうか?結構面白いと思いませんか?(私だけかも。。。)

もし、ご意見やご要望がある方は、遠慮なくご連絡いただけたらと思います。

個人的には作っていて結構面白いと思ってますので、もうちょっとまともな形になるまで、ちょこちょこといじっていこうと思っています。目標は、Relaxerのようなスキーマ定義言語を元にしたコード自動作成ですね(^-^; でも、PHP4.3.0の正式リリースまでにDOM XML関数が全然変わってたりして。。。(-"-;



About This Site |  Privacy Policy |  Contact
Copyright © 1999 - 2005 by Hideyuki SHIMOOKA all rights reserved.