phpの質問です。

以下のデータがあるとして
<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
よろしくお願いします

回答の条件
  • 1人5回まで
  • 13歳以上
  • 登録:2011/10/20 14:19:06
  • 終了:2011/10/21 18:33:32

ベストアンサー

id:tobeoscontinue No.2

tobeoscontinue回答回数214ベストアンサー獲得回数542011/10/20 21:37:52

ポイント100pt

またしても前回の応用です。

データーは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>

その他の回答(1件)

id:tdoi No.1

tdoi回答回数174ベストアンサー獲得回数752011/10/20 16:49:29

ポイント50pt

こんな感じでいかがでしょう?

前回の質問と同じようにパースして、再帰的に処理をしているだけです。

ツリー状にするのは、とりあえずインデントで明示するようにしましたが、これでいいでしょうか?

もっと効率のよいコードも書けると思いますが、目的が分からないのでこのくらいで。

<?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)

何かの参考になれば。

id:vfr6822

うまく出力結果が表示できませんでしたがありがとうございました!

2011/10/21 18:32:04
id:tobeoscontinue No.2

tobeoscontinue回答回数214ベストアンサー獲得回数542011/10/20 21:37:52ここでベストアンサー

ポイント100pt

またしても前回の応用です。

データーは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>
  • id:vfr6822
    いつもありがとうございます!
    出力したいイメージが作れずなかなか全てをお伝えできなくすみませんでした。
    とても参考になりました。ありがとうございます!

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません