Pear XML_Serializerで多重階層のXMLを生成する

XML_Serializerは配列からXMLを生成できる便利なライブラリです。
以下のような、「1つの階層に同じタグが並列に並ぶもの」が複数の階層に現れる場合の生成法がわからなかったので、メモしておきます。

<?xml version="1.0" encoding="UTF-8"?>
<data>
    <drink id="1">
        <name>コーラ</name>
        <item>ダイエットコーラ</item>
        <item>バニラコーク</item>
    </drink>
    <drink id="2">
        <name>ペプシ</name>
        <item>ペプシ バオバブ</item>
        <item>ペプシ しそ</item>
    </drink>
</data>

この場合、「data」の子ノードに「drink」が並列に複数並び、「drink」の子ノードに「item」が複数並んでいます。

結論から言えば、オプションの「defaultTagName」指定がポイントでした。

検証環境は以下の通りです。
OS:Ubuntu10.10
PHP:5.3.3

では始めます。(以下、rootユーザで作業しています)

1.Pearのインストール

apt-get install php-pear

2.XML_Serializerのインストール

sudo pear install --alldeps xml_serializer-beta

3.確認

pear list で確認します

INSTALLED PACKAGES, CHANNEL PEAR.PHP.NET:
=========================================
PACKAGE          VERSION STATE
Archive_Tar      1.3.7   stable
Console_Getopt   1.2.3   stable
PEAR             1.9.1   stable
Structures_Graph 1.0.3   stable
XML_Parser       1.3.4   stable
XML_Serializer   0.20.2  beta
XML_Util         1.2.1   stable
4.ソース準備
<?php
require_once("XML/Serializer.php");

// 出力したい内容
$data = array( 0 => array('_attributes' => array('id'=> '1'),
                          'name' => 'コーラ',
                          0 => 'ダイエットコーラ',
                          1 => 'バニラコーク'
                          ),
               1 => array('_attributes' => array('id'=> '2'),
                          'name' => 'ペプシ',
                          0 => 'ペプシ バオバブ',
                          1 => 'ペプシ しそ'
                         )
               );

// XML生成時のオプション
 $options = array(
      "indent"          => "\t",
      "linebreak"       => "\n",
      "typeHints"       => false,
      "addDecl"         => true,
      "encoding"        => "UTF-8",
      "rootName"        => "data",
      "rootAttributes"  => array(),
      "defaultTagName"  => array('data'=> 'drink',
                                 'drink' => 'item'
                                 ),
      "attributesArray" => "_attributes"
      );

$serializer = new XML_Serializer($options);
$serializer->serialize($data);
$result = $serializer->getSerializedData();

header("Content-Type: text/xml; charset=utf-8");
echo $result; 
5.ブラウザから確認

ちゃんと出力されました。

ポイントは$optionの

"defaultTagName"  => array('data'=> 'drink',
                                'drink' => 'item'
                           ),

という部分です。
まず、rootNameに「data」を指定しているため、
出力したい内容の$data全体がdataタグで囲まれる形になります。
そして、defaultTagNameで「'data'=>'drink'」と指定することで、
$dataの1次元目(= dataタグの子ノード)のキーが数字だと自動的に
drinkタグで囲まれます。
itemタグも同様のロジックで囲まれますね。


余談ですが・・・
XML_Serializerを使っていて、
「drinkやitemの階層で、drink/itemと違うタグを複数並列に配置したい場合はどうすればよいか?」
というのが気になっています。

例えば、

<?xml version="1.0" encoding="UTF-8"?>
<data>
    <drink id="1">
        <name>コーラ</name>
        <name>cola</name>
        <item>ダイエットコーラ</item>
        <item>バニラコーク</item>
    </drink>
    <drink id="2">
        <name>ペプシ</name>
        <name>pepsi</name>
        <item>ペプシ バオバブ</item>
        <item>ペプシ しそ</item>
    </drink>
</data>

のようにnameタグを複数出力したい場合はどうすればよいのでしょうか?
(この例はあまりよくないので、"english_name"タグとかに変えたくなりますがそこはスルーします!)

defaultTagNameで'drink' => 'item'と置いてしまったら、

array('_attributes' => array('id'=> '1'),
	                      'name' => 'コーラ',
                              'name' => 'cola',
	                       0 => 'ダイエットコーラ',
	                       1 => 'バニラコーク'
	                     ),

と書いたとしてもname要素がcolaに上書きされるだけです。。

上のXMLをテキストファイルに保存してブラウザに読み込ませるとちゃんと表示されることから
XML構造として誤りではないようですし、何とかできたらいいですね。
恐らくPHPとの関係上仕方ない気もしますが、「いや出来るぜ☆」という方はぜひ御一報下さい!

VirtualBox3.2.10 と Ubuntu10.10 で開発環境を構築する-②Apache設定編

テスト用のサイトをNameVirtualHostで2つ作り、windowsからアクセスしてみます。
(以下では 「sudo su -」でrootで作業しています)

まず、現状の設定は以下のようになっています。
・設定ファイル(/etc/apache2/apache2.conf)の229行目あたり

# Include the virtual host configurations:
 Include sites-enabled/

でsites-enabled/以下のファイルも設定ファイルとして読み込んでいる。
・sites-enabledではリンクファイルによりsites-available/defaultを参照している。

/etc/apache2/sites-enabled# ll
合計 0
lrwxrwxrwx 1 root root 26 2010-11-03 15:11 000-default -> ../sites-available/default

このdefaultの中に、現在動いているサイトの設定が書かれています。
defaultの中身は

/etc/apache2/sites-available# head -15 default
<VirtualHost *:80>
        ServerAdmin webmaster@localhost

        DocumentRoot /var/www
        <Directory />
                Options FollowSymLinks
                AllowOverride None
        </Directory>
        <Directory /var/www/>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride None
                Order allow,deny
                allow from all
        </Directory>

/etc/apache2/sites-available#

このようになっていて、 /var/www がドキュメントルートになってますので、
ここに置いたファイルがブラウザから見れることになります。

/var/www# head index.html
<html><body><h1>It works!</h1>
<p>This is the default web page for this server.</p>
<p>The web server software is running but no content has been added, yet.</p>
</body></html>
/var/www#

動作確認の時にブラウザで見た「It works!」というのはここに書かれていたのでした。

これをこのようにしたいと思います。
・/etc/apache2/vhosts に設定ファイルを置く。
・/www/{環境名}/htdocs をドキュメントルートとする

まずは今公開中のサイトを閉じます。(設定ファイルから消します)

/etc/apache2# cp apache2.conf apache2.conf_20101120  # バックアップ
/etc/apache2# vi apache2.conf
 (略)
/etc/apache2# diff apache2.conf_20101120 apache2.conf
230c230
< Include sites-enabled/  # 以前はこうだったインクルードディレクトリを・・・
---
> Include vhosts/  # こう変更しました。
/etc/apache2#

次に、新しく作るサイトの設定ファイルを書きます
(gakaxy, sisyamoの2サイトを作り、それぞれ
http://galaxy.localhosthttp://sisyamo.localhost
でブラウザからアクセスする想定です)

/etc/apache2# mkdir vhosts
/etc/apache2# cd vhosts
/etc/apache2/vhosts# vi vhosts.conf
 (略)
/etc/apache2/vhosts# cat vhosts.conf
<VirtualHost *:80>
  ServerName galaxy.localhost
  DocumentRoot /www/galaxy/htdocs
  LogLevel  warn
  LogFormat "%h %l %u %t \"%r\" %>s %b" common
  ErrorLog  /var/log/apache2/galaxy/error.log
  CustomLog /var/log/apache2/galaxy/access.log common
</VirtualHost>

<VirtualHost *:80>
  ServerName sisyamo.localhost
  DocumentRoot /www/sisyamo/htdocs
  LogLevel  warn
  LogFormat "%h %l %u %t \"%r\" %>s %b" common
  ErrorLog  /var/log/apache2/sisyamo/error.log
  CustomLog /var/log/apache2/sisyamo/access.log common
</VirtualHost>
/etc/apache2/vhosts#

ログファイル用ディレクトリを準備します。

/etc/apache2/vhosts# cd /var/log/apache2
/var/log/apache2# mkdir galaxy
/var/log/apache2# mkdir sisyamo

ログローテーションの設定をします。
以下のように /etc/logrotate.d/apache2 を変更しました。

/etc/logrotate.d# cat apache2
/var/log/apache2/galaxy/*.log /var/log/apache2/sisyamo/*.log {
        weekly
        missingok
        rotate 52
        compress
        delaycompress
        notifempty
        create 640 root adm
        sharedscripts
        postrotate
                /etc/init.d/apache2 reload > /dev/null
        endscript
}
/etc/logrotate.d#

ドキュメントルートにファイルを置きます。

/etc/logrotate.d# cd /
/# mkdir www
/www# mkdir galaxy
/www# mkdir sisyamo
/www# cd galaxy
/www/galaxy# mkdir htdocs
/www/galaxy# cd htdocs
/www/galaxy/htdocs# echo "<html>\n<body>\nthis is galaxy\n</body>\n<html>" > index.html
/www/galaxy/htdocs# cd ../../sisyamo
/www/sisyamo# mkdir htdocs
/www/sisyamo# cd htdocs
/www/sisyamo/htdocs# echo "<html>\n<body>\nthis is sisyamo\n</body>\n<html>" > index.html
/www/sisyamo/htdocs#

apacheを再起動して、設定を有効にします。

/www/sisyamo/htdocs# apache2ctl configtest  # 設定ファイルの文法チェック
Syntax OK
/www/sisyamo/htdocs#
/www/sisyamo/htdocs# /etc/init.d/apache2 restart
 * Restarting web server apache2
 ... waiting    ...done.
/www/sisyamo/htdocs#

これで公開するファイルが用意できましたが、まだブラウザからアクセスすることはできません。
なぜなら、"galaxy.localhost"のアクセス先(Ubuntu)のIPがDNSサーバに登録されていないからです。
そこで、windowsのローカルのhostsファイルに設定を書きます。
windows7ではc:\windows\system32\drivers\etc にあります。
これに以下の2行を追加します。
192.168.56.101 galaxy.localhoset
192.168.56.101 sisyamo.localhoset

これで、ブラウザから
http://galaxy.localhost/http://sisyamo.logalhost/
にアクセスしてみてください。
それぞれ「this is galaxy」「this is sisyamo」というのが見えたらOKです!

VirtualBox3.2.10 と Ubuntu10.10 で開発環境を構築する-①インストール編

VirtualBoxUbuntuでLAMP環境を構築するメモです。

普段、Windows上でソースを書いて、Linux上で動作確認をする駆け出しのエンジニア(僕ですね)が対象です。
今回はWindows7上に構築しています。
もし間違いなどに気づいてしまった方はこそっと教えてください!

VirtualBoxUbuntuを用意する

http://www.virtualbox.org/
Downloads → VirtualBox 3.2.10 for Windows hosts からダウンロードします。

http://www.ubuntulinux.jp/
Ubuntuの入手 → 日本語RemixCDイメージのダウンロード → ubuntu-ja-10.10-desktop-i386.iso(CDイメージ)
からダウンロードします。

VirtualBoxをインストールし、仮想マシンを作成する

VurtyakBoxのインストールはaldente-studioさんが詳しいのでそちらを参考に!
VirtualBoxでの仮想環境構築1点変更・・・ ネットワークの設定ではアダプタ1を「ホストオンリーアダプタ」にしてください。その方がwindowsからつなぐのが楽そうです。。

仮想環境にUbuntuをインストールする部分は10.10だと画面が若干代わるので
一応キャプチャを載せておきます。
[起動]ボタンをクリックし、仮想マシンを起動します。
マウス統合機能についてのポップアップが出ますので[OK]をクリックします。


[Ubuntuをインストール]をクリック


[アップデートをダウンロードする]にチェックします。
Ubuntuのデスクトップ機能に興味があればサードパーティソフトウェアのインストールにもチェックしておきましょう。


[ディスク全体を削除してから使用する]がチェックされた状態で[進む]


[インストール]をクリック


[進む]をクリック


[Japan]が選択された状態で[進む]をクリック


アカウント情報を設定します。
(ここで設定した「コンピュータの名前」は後ほど使います。)

[進む]を押すと再起動してインストール完了です。

Ubuntuの設定をする

ssh,Apache,MySQLの設定をしていきます。

まず画面上部のパネルに端末のランチャを追加しておきましょう。
パネルを右クリック→パネルへ追加→アプリケーションのランチャ...
→「アクセサリ」の左端の三角をクリック→端末→追加 で行えます。


こんな感じで追加できたと思います。

次にサーバのパッケージを入れましょう。
UbuntuではSynapticというパケージマネージャがあるのでそれを使います。

まずシステム→システム管理→Synapticパケージ・マネージャ から起動します。
(パスワードの入力が求められるので入力してください)


まずwindows側からsshで接続できるようにするためにsshのデーモン(sshd)を入れましょう。
クイック検索の窓にsshと入れ、出てきたsshパッケージの左端の四角をクリックし、「インストール指定」を選択します。

この時、依存関係のあるパッケージも入れるか聞かれますので「マーク」します。


次に「php5」と検索してTOPに出てくるパッケージをインストール指定します。
この時依存関係のあるパッケージとしてapacheも出てくるのでマークします。
MySQLについては「mysql」と検索して「mysql-server-5.1」をインストール指定します。
(あと、「zsh」と検索して入れておくと幸せになれそうです。
最強のシェル、それは「zsh」

パッケージを選択し終えたら、「適用」でインストールします。

ダウンロードが始まり...


終わるとMySQLのrootアカウントのパスワードを聞かれるので設定します。
(Linuxのrootアカウントではなく、MySQLのユーザとしてのrootアカウントです)


その後インストールを待てば完了です!

動作確認

では動作確認をしてみます。
端末から
・「ps aux | grep sshd」でsshdの動作確認
・「php -v」でPHPのバージョン確認
・「mysql -u root -p」でMySQLへログイン確認
ブラウザから
・「http://localhost」にアクセスすると「It works!」と表示される

上記でちゃんとインストールされたことが確認できると思います。

次に、windowsからのsshやhttpの接続ですが、
VirtualBoxの設定でネットワークアダプタ1をホストオンリーネットワークにしていることで
IP指定でそのまま接続できます。

ではUbuntuのIPを確認しましょう。
端末から「/sbin/ifconfig | grep inet」と入力してください。


192.168・・というのがwindowsと同じローカルネットワーク上のアドレスになりますので
この場合teraterm等で「192.168.56.101」でssh接続できます。
windows上のブラウザからも「http://192.168.56.101」で「It works!」
というのが見えます。
(windowsのコマンドプロンプトで「ipconfig」を実行すると、
windows自身のホストオンリーネットワーク上のアドレスが192.168・・であることが確認できます。)

次回はApaheの設定をして2つのサイトを作ってみまーす。