以下のデータがあるとして
<rank point="9000" order="1" index="1">
<team area3="青葉区" area2="横浜市" area1="神奈川県" email="" url="" name="AAAAA" id="00001"/> </rank>
<rank point="8000" order="2" index="2">
<team area3="青葉区" area2="横浜市" area1="神奈川県" email="" url="" name="BBBBB" id="00002"/> </rank>
<rank point="7000" order="3" index="3">
<team area3="西区" area2="横浜市" area1="神奈川県" email="" url="" name="CCCCC" id="00003"/></rank>
<rank point="6000" order="4" index="4">
<team area3="瀬谷区" area2="横浜市" area1="神奈川県" email="" url="" name="DDDDD" id="00004"/> </rank>
<rank point="5000" order="5" index="5">
<team area3="西区" area2="横浜市" area1="神奈川県" email="" url="" name="EEEEE" id="00005"/> </rank>
出力結果を
神奈川県(5)
└─横浜市(5)
└─西区(2)
└─青葉区(2)
└─瀬谷区(1)
と、yahooUIのツリー表示を使って(使わなくてもいいんですが)
件数を表示できるようなやり方を教えてください。
関連した過去の質問です
http://q.hatena.ne.jp/1311135822
よろしくお願いします
またしても前回の応用です。
データーはxmlとしたのでrankの外を何かで囲む必要があります。
肝は$area["$a1"]["$a2"]["$a3"][]の部分です。連想配列を使うことで同じものは勝ってに集まるのでただループして追加していくだけです。
array((string)$rank["point"], (string)$rank["order"],(string)$rank->team["id"], (string)$rank->team["name"],(string)$rank->team["url"], (string)$rank->team["email"]);
の部分は応用として使うことがあるかなぁということで今は使用してません。
連想配列で階層は表現できているのですが件数は拾はないといけないのでソースが汚いです。
本来は県->市->区の順に処理できればいいのですが区を処理して件数を求めてから市を処理し、更に県を処理するということをしています。
後はhtmlにscriptを埋め込んで終了です。
phpのコードとjavascriptのコードが混在して可読性が悪いです。
javascriptでsample.xmlのようなデータを落としてツリーを構築するやりかたの方がいいのではないでしょうか。
<?php function tree_view_xml($name, $xml, $CR="\n") { $xml = simplexml_load_file($xml); $area = array(); foreach($xml->rank as $rank) { $a1 = $rank->team["area1"]; $a2 = $rank->team["area2"]; $a3 = $rank->team["area3"]; $area["$a1"]["$a2"]["$a3"][] = array((string)$rank["point"], (string)$rank["order"], (string)$rank->team["id"], (string)$rank->team["name"], (string)$rank->team["url"], (string)$rank->team["email"]); } $yui_tree ='var tree; window.onload = function(){ tree = new YAHOO.widget.TreeView("treeData"); var root = tree.getRoot();'.$CR; foreach($area as $pref=>$a2) { $a2_tree = ''; $a2_count = 0; foreach($a2 as $city=>$a3) { $a3_tree = ''; $a3_count = 0; foreach($a3 as $dist=>$m) { $a3_count += count($m); $a3_tree .= 'new YAHOO.widget.TextNode("'.$dist.'('.count($m).')", city, false);'.$CR; } $a2_count += $a3_count; $a2_tree .= "var city = new YAHOO.widget.TextNode(\"${city}(${a3_count})\", pref, false);".$CR.$a3_tree; } $yui_tree .= "var pref = new YAHOO.widget.TextNode(\"${pref}(${a2_count})\", root, false);".$CR.$a2_tree; } return $yui_tree.'tree.draw();'.$CR.'}'.$CR; } ?> <html> <head> <meta http-equiv="content-type" content="text/html;charset=utf-8"> <title>vfr6822:1319087945</title> <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.8.1/build/treeview/assets/skins/sam/treeview.css"> <script type="text/javascript" src="http://yui.yahooapis.com/2.8.1/build/yahoo-dom-event/yahoo-dom-event.js"></script> <script type="text/javascript" src="http://yui.yahooapis.com/2.8.1/build/treeview/treeview-min.js"></script> <script type="text/javascript"><!-- <?php echo tree_view_xml("treeData", "./sample.xml") ?> // --></script> </head> <body> <h1>vfr6822:1319087945</h1> <form> <input type="button" value="全て展開" onClick="tree.expandAll()"> <input type="button" value="全て折り畳む" onClick="tree.collapseAll()"> </form><div id="treeData"></div> </body> </html>
こんな感じでいかがでしょう?
前回の質問と同じようにパースして、再帰的に処理をしているだけです。
ツリー状にするのは、とりあえずインデントで明示するようにしましたが、これでいいでしょうか?
もっと効率のよいコードも書けると思いますが、目的が分からないのでこのくらいで。
<?php $result = parseXml('sample.xml'); outputResult($result); function parseXml($filename) { $xml = file_get_contents($filename); $document = new SimpleXMLElement($xml); $result = array(); foreach ($document->rank as $rank) { $area1 = strval($rank->team['area1']); $area2 = strval($rank->team['area2']); $area3 = strval($rank->team['area3']); if (!isset($result[$area1])) { $result[$area1] = array(); } if (!isset($result[$area1][$area2])) { $result[$area1][$area2] = array(); } if (!isset($result[$area1][$area2][$area3])) { $result[$area1][$area2][$area3] = 0; } ++$result[$area1][$area2][$area3]; } return $result; } function outputResult($result, $offset = '') { foreach ($result as $key => $node) { echo $offset . $key . "(" . getCount($node) . ")\r\n"; if (is_array($node)) { outputResult($node, $offset . "----"); } } } function getCount($node) { if (is_array($node)) { $count = 0; foreach ($node as $child) { $count += getCount($child); } } else { $count = $node; } return $count; } ?>
こんな出力になります。
神奈川県(5) ----横浜市(5) --------青葉区(2) --------西区(2) --------瀬谷区(1)
何かの参考になれば。
出力したいイメージが作れずなかなか全てをお伝えできなくすみませんでした。
とても参考になりました。ありがとうございます!