はじめて投稿させていただきます。
DBに登録されているツリーテーブルを配列に取り込み、
xmlのツリーにしてファイルに保存したいと考えております。
DBのデータは以下のようになっております。
idcidattname
0-1Da
10Fb
20Fc
中略
33-1Dd
3433De
3534Ff
3634Fg
中略
262-1Dh
263262Di
264263Fj
id:インデックス
cid:子番号(idに同じ番号を持つものを親とする)(-1は最上階層の親)
att:DはディレクトリFは末端
name:表示する名前
これを展開しながらxmlタグを挿入していきたいのですが
nameを出力するタイミングでタグを挿入しようとすると末端のものしか
開始・終了タグで挟むことができません。
入れ子になっている場合の親の終了タグは全ての子供が終わった後に、階層の深さの数だけを最後に足してやりたいのです。
不規則な配列なのでforeachでするくらいしかわからず、
やってみたのですがatt=="D"なら再帰処理で繰り返し、
Dでなくなったら末端を書くくらいの事しかできず、
終了タグをどういった処理で入れたらよいかわかりません。
800文字制限に引っかかってしまい実際の配列の形はのせれませんでした。。
分割投稿も禁止のようで。。
各要素を持つ末端配列はわかりやすいように、仮に一つであっても次元を一つ下げて0番目の配列に格納しております。
もしかしたら配列への格納方法もよくないのかもしれません。。
・後々扱いやすいような配列への格納の仕方
・配列を展開しながらのタグの挿入方法
をどなたか良い案がありましたら宜しくお願い致します。
No.3ベストアンサー
- 回答日時:
面白そうなので、プログラムを書いてしまいました^^。
DBからデータを読みながら処理するのではなく、DBからのデータを一旦$dbdataに入れて処理をする前提のプログラムです(DBからSELECTする部分は省略してます)。DBのデータが、きれいな順番で並んでいないことがあるならば、そうしないとうまく処理できないと思います。
内部的にはDOMでデータを扱ってます。
>・後々扱いやすいような配列への格納の仕方
配列よりもクラスのオブジェクトにするのが一番扱いやすいと思います。クラスを自作しても良いのですが、色々と機能を追加していくとDOMに近づいていくように思います。なので、DOMを使っています。
それから、ディレクトリ階層を下に辿っていく処理は再帰を利用しています。
<?php
$dbdata
= array(
array('id'=>'0','cid'=>'-1','attr'=>'D','name'=>'a'),
array('id'=>'1','cid'=>'0','attr'=>'F','name'=>'b'),
array('id'=>'2','cid'=>'0','attr'=>'F','name'=>'c'),
array('id'=>'33','cid'=>'-1','attr'=>'D','name'=>'d'),
array('id'=>'34','cid'=>'33','attr'=>'D','name'=>'e'),
array('id'=>'35','cid'=>'34','attr'=>'F','name'=>'f'),
array('id'=>'36','cid'=>'34','attr'=>'F','name'=>'g'),
array('id'=>'262','cid'=>'-1','attr'=>'D','name'=>'h'),
array('id'=>'263','cid'=>'262','attr'=>'D','name'=>'i'),
array('id'=>'264','cid'=>'263','attr'=>'F','name'=>'j'),
);
// 扱いづらいので、以下のようなハッシュ形式データにする。
// array('0' => array('cid'=>'-1','attr'=>'D','name'=>'a'),
// '1' => array('cid'=>'0','attr'=>'F','name'=>'b'),
$hash = array();
foreach ($dbdata as $arr) {
$id = $arr['id'];
unset($arr['id']);
$hash[$id] = $arr;
}
// DOMDocument作成
$doc = new DOMDocument('1.0', 'UTF-8');
$doc->formatOutput = true;
// hoge呼び出し
$hoge = new hoge($doc, $hash);
$doc->appendChild($hoge->exec());
echo $doc->saveXML();
class hoge {
var $doc;
var $hash;
function hoge($doc, $hash) {
$this->doc = $doc;
$this->hash = $hash;
}
function exec($id = '-1') {
// 初回呼び出し
if ($id == '-1') {
// root要素作成
$retnode = $this->doc->createElement('root');
}
// 初回以外
else {
// attr (D or F)
$attr = $this->hash[$id]['attr'];
// name
$name = $this->hash[$id]['name'];
// D or Fという要素作成
$retnode = $this->doc->createElement($attr);
// id属性設定
$retnode->setAttribute('id', $id);
// name属性設定
$retnode->setAttribute('name', $name);
}
// 初回 or attr == D の場合(子供がいる)
if ($id == '-1' || $attr == 'D') {
foreach ($this->hash as $k => $v) {
// 子要素か?
if ($v['cid'] == $id) {
// 再帰呼び出しして、$retnodeの子要素にする
$retnode->appendChild($this->exec($k));
}
}
}
return $retnode;
}
}
?>
インデントは全角スペースを使っているので、半角スペースに置き換えてください。
なお、数日間出掛けてしまうので、追加のご質問頂いても返答できないかもしれません。申し訳ありません。
もし何かの役に立てば幸いです。
この回答への補足
書き込みをするスペースがここくらいしかなかないようなのでここで報告させていただきます。
結論から先に言いますと希望する挙動を得ることができました。
ありがとうございましたm(_ _)m
PHPマニュアルページのDOMの部分とにらめっこしながらfdsjaklfjas様が書いてくださったソースを実データに合わせた形に変更し、DBからデータを取得してスクリプトを走らせたところ日本語がやはり化けましたので、取得しながらエンコードをかけたらうまくいきました。
$doc = new DOMDocument('1.0', 'UTF-8');
この段階で
$doc = new DOMDocument('1.0', 'Shift-JIS');
とすることは出来ないのですね^^;
あと今回は
<entity id="1" pic="hoge.jpg" t_name="item_0001" url="contents" image="images/dir.gif" imageopen="images/diropne.gif" name="商品1"/>
のようにid等必要なものを全てentity要素の属性として1つのタグの中に書く事をfdsjaklfjas様のソースから教えていただいたのですが、
上記タグを例えば
<entity id="1">
<pic>hoge.jpg</pic>
<t_name>item_0001</t_name>
<url>contents</url>
<image>images/dir.gif</image>
<imageopen>images/diropne.gif</imageopen>
<name>商品1</name>
</entity>
のようにentity配下のpic、t_name要素というような形を生成することは可能なのでしょうか?
createElementで作成してappendChildで追加するとどうしても
<pic>は<pic />というタグ1つで終了する形になってしまいまして。。
勉強の為、もし宜しければ今回作成していただいたプログラムを題材にそういったことが出来るのなら教えてくださいm(_ _)m
具体的にプログラムを作っていただきありがとうございます!
私の方も休み明けにならないとソースを触れないので
休み明けになりましたら早速試してみます!
もし実際に組んでみて質問したいことがでてきたら数日後なら
大丈夫でしょうか^^;
その時はまた宜しくお願い致します。
No.4
- 回答日時:
>のようにentity配下のpic、t_name要素というような形を生成することは可能なのでしょうか?
$e1 = $doc->createElement('entity');
$e2 = $doc->createElement('pic', 'hoge.jpg');
$e3 = $doc->createElement('t_name', 'item_0001');
$e1->appendChild($e2);
$e1->appendChild($e3);
でどうでしょうか。
回答ありがとうございます。
待っている間に考えていました。
<?xml version="1.0" encoding="utf-8" ?>
- <entity>
- <aaa>
- <bbb>
<pic>hoge.jpg</pic>
<t_name>item_0001</t_name>
</bbb>
</aaa>
</entity>
上のような形ってどうやるんだろうって思っていたのですが
<?php
$doc = new DOMDocument('1.0', 'utf-8');
$e1 = $doc->createElement('entity');
$e2 = $doc->createElement('aaa');
$e3 = $doc->createElement('bbb');
$e4 = $doc->createElement('pic', 'hoge.jpg');
$e5 = $doc->createElement('t_name', 'item_0001');
$e3->appendChild($e4);
$e3->appendChild($e5);
$e2->appendChild($e3);
$e1->appendChild($e2);
$doc->appendChild($e1);
echo $doc->saveXML();
?>
のように深い階層から順番にappendChildを記述していけば良いのですね^^
DOMDocumentというのは今回初めて使ってみたのですがすごく勉強になりました。
どうもありがとうございました m(_ _)m
No.2
- 回答日時:
多分、DOMを使った方がいいかもしれない。
。。自分も勉強中だからまだよくわからないけど新規に作るなら
$doc=new DOMDocument('1.0','UTF-8');
$doc->appendChild($doc->createElement('root'));
でもこれver5じゃないと使えないみたい。
この回答への補足
アドバイスありがとうございます
>でもこれver5じゃないと使えないみたい。
ver5とはPHP5ということでしょうか?
もしそうでしたらこちらの環境はPHP5です。
ですが、DOMDocumentというのを使用すればまっさらな状態から
不規則階層のxmlツリーを作成できるのでしょうか?
現実問題として不規則階層を持つツリーデータをDBから取り出して
xmlツリーを作成すること自体は可能なのでしょうかね・・・汗
階層数があらかじめ決まっていれば何とかなりそうな予感はするのですが。。。
引き続き、良い方法がありましたらどなたかご教授お願い致しますm(__)m
DOMDocumentを使用して
fdsjaklfjas様のソースをこちらの環境に合わせながら
なんとか希望通りのものを作成することができました。
DOMDocumentってすごいですね^^;
ありがとうございました。
No.1
- 回答日時:
単純ループじゃなく再帰呼出(リカーシブコール)系で組み直すとか
それだと効率悪いか・・・もう少し考えないとだめかな・・・
この回答への補足
以下のような再帰処理で配列を作ってみたのですが
この配列でその後の処理がいけるのかいけないのか・・・。
自分の力ではここからxmlツリーを作成することが出来ませんでした。。
function GetTree($val)
{
$sql = "select * from tree_tbl where cid = ".$val." order by id";
if(!($result = mysql_query($sql)))
{
return;
}
$leaves = "";
while($row = mysql_fetch_assoc($result))
{
$leaf = "";
$leaf[0] = $row;
//子がある場合
if($row["att"]=="D"){
$leaf[1] = GetTree($row["id"]);
}
$leaves[] = $leaf;
}
return $leaves;
}
$tree = GetTree(-1);
print_r($tree);
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- PHP 配列の値の更新方法について 1 2022/08/05 09:49
- Java Java 南京錠 2 2023/02/04 11:46
- C言語・C++・C# C#の問題です。 文字列型の配列 s[100] にキーボードから入力された100文字以内の文字列(単 2 2022/06/22 15:18
- Java javaでのプログラム(配列)について質問です. 2 2022/10/14 22:27
- Visual Basic(VBA) ファイル全てを .xlsm に変更したところ、プログラムが途中で落ちてしまっています 17 2022/12/07 12:03
- Excel(エクセル) Excelにて、フォルダ内のTextファイルをマクロで統合すると文字化けしてしまう時の解消コード 4 2023/01/01 07:32
- Visual Basic(VBA) マクロVBA 1シートをまとめる 閉じ方 初心者 SOS! 1 2022/06/17 14:54
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
- Ruby 初心者プログラミング 3 2022/10/12 11:31
- Java Java モンスターブリーダー 1 2023/02/05 09:44
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
特定の文からメールアドレスの...
-
行列
-
CArrayの要素としてCStringArra...
-
php で1から100までの素数の表...
-
プログラミングのPythonのnoteb...
-
【PHP】配列のキー名の修正は可...
-
スカラーのベクトル微分
-
CArrayのソート
-
読み(あ行~わ行)ごとに分け...
-
配列の添え字が小数だとどうなる?
-
通常の添字か連想添字かの判別
-
配列の要素(value)に、変数を...
-
$_SESSIONに二次元配列を使える...
-
別ファイルの構造体の値を読み...
-
プルダウンメニューにDBの内容...
-
String だと「 ByRef引数の型が...
-
漢字のソートについて
-
マッチング処理(1:N)
-
foreachのなかで次のキーを参照...
-
多次元配列の扱い方
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
プログラミングのPythonのnoteb...
-
スカラーのベクトル微分
-
特定の文からメールアドレスの...
-
CArrayの要素としてCStringArra...
-
C言語 最大値と最小値を求めて...
-
行列
-
読み(あ行~わ行)ごとに分け...
-
配列の要素(value)に、変数を...
-
C言語の配列をPush(追加)する...
-
STLのvectorで作った配列をメン...
-
【PHP】配列のキー名の修正は可...
-
php で1から100までの素数の表...
-
Perlで重複行を削除したい
-
fgetc関数について
-
CArrayのソート
-
ファイルの書き込みについて教...
-
配列の添え字が小数だとどうなる?
-
PHPのmin関数、「1」以上の数値...
-
forとかで連番の変数を一気に格...
-
delphi 2次元配列がわかりません
おすすめ情報