download.bg
 Вход Списание  Новини  Програми  Статии  Форум  Чат   Абонамент  Топ95   Архив 

PHP - обхождане на дърво. Нещо патладясах. Help!

<1 2 >

Автор
Съобщение
phrozencrew
Вто, 17.08.10, 19:18

RE: PHP - обхождане на дърво. Нещо патладясах. Help!

” супер

нещата отиват към XPath май? -> ako работата c XML ти допадне, ще е добре да отвориш 1тема от рода на XPath: въпроси и отговори, че не съм много в час там.

Edit:
http://garr.dl.sourceforge.net/sourceforge/phpxpath/PhpXPath-3.5.zip
http://heanet.dl.sourceforge.net/sourceforge/phpxpath/PhpXPath-3.5-Tests.zip

Малко старичка тема, но пък полезна. koko5, послушах ти съвета и се насочих към XPath. Супер полезен инструмент за ДБ-заявки към XML-файл. Към конкретният пример ще приложа една проста схема за обхождане на XML-дървото. В случая обхождането е нагласено за образуване на проста дървовидна меню-система, която лесно може да се интегрира към CMS-система. Може да е полезно и на някой друг, затова прилагам сорса.
XML-файла: hrana.xml
<?xml version="1.0"?>
<hrana>
	<hrana>
		<hrana_name>Food</hrana_name>
		<hrana_url>/food</hrana_url>
		<hrana_id>1</hrana_id>
		<hrana>
			<hrana_name>Fruit</hrana_name>
			<hrana_url>/food/fruit</hrana_url>
			<hrana_id>2</hrana_id>
			<hrana>
				<hrana_name>Red</hrana_name>
				<hrana_url>/food/fruit/red</hrana_url>
				<hrana_id>3</hrana_id>
				<hrana>
					<hrana_name>Cherry</hrana_name>
					<hrana_url>/food/fruit/red/cherry</hrana_url>
					<hrana_id>4</hrana_id>
				</hrana>
			</hrana>
			<hrana>
				<hrana_name>Yellow</hrana_name>
				<hrana_url>/food/fruit/yellow</hrana_url>
				<hrana_id>5</hrana_id>
				<hrana>
					<hrana_name>Banana</hrana_name>
					<hrana_url>/food/fruit/red/banana</hrana_url>
					<hrana_id>6</hrana_id>
				</hrana>
			</hrana>
		</hrana>
		<hrana>
			<hrana_name>Meat</hrana_name>
			<hrana_url>/food/meat</hrana_url>
			<hrana_id>7</hrana_id>
			<hrana>
				<hrana_name>Beef</hrana_name>
				<hrana_url>/food/fruit/beef</hrana_url>
				<hrana_id>8</hrana_id>
			</hrana>
			<hrana>
				<hrana_name>Pork</hrana_name>
				<hrana_url>/food/fruit/pork</hrana_url>
				<hrana_id>9</hrana_id>
			</hrana>
		</hrana>
	</hrana>
</hrana>

Изтегляне: hrana.xml
PHP-обхождащият скрипт:
<?php
function printHranaMap(){
    return printHranite(simplexml_load_file("hrana.xml"));
}
 
function printHranite(SimpleXMLElement $parent){
    $html = "<ul>\n";
    foreach ($parent->hrana as $hrana){
        $html .= printHrana($hrana);
    }
    $html .= "</ul>\n";
    return $html;
}
 
function printHrana(SimpleXMLElement $hrana){
    $html = '<li id="hrana'.$hrana->hrana_id.'"><a href="'.$hrana->hrana_url.'">'.$hrana->hrana_name.' ['.$hrana->hrana_id.']</a>';
 
    if (isset($hrana->hrana)){
        // Proverka dali ima <hrana/> children
        $html .= printHranite($hrana);
    }
 
    $html .= "</li>\n";
    return $html;
}
 
echo printHranaMap();
?>

Изтегляне: hrana.php
Изход:

Файловете са преименувани от сървара, затова целия проект, заедно с изпълнението на скрипта:
hrana.zip
==================================================================

Да погледнем нещата обаче под друг ъгъл. Ако имаме или планираме да имаме меню, което е съставено само от 2 слоя - главен и субменюта, тогава XPath би могъл много да улесни задачата ни по парсването на XML-файла. Примерно имаме следната схема:

В този случай, тъй като имаме кирилски символи ЗАДЪЛЖИТЕЛНО работим в UTF-8 кодиране и примерно XML-файла ни може да изглежда опростено така:
<?xml version="1.0"?>
<menuta>
	<menu name="Ядене" url="/iadene">
		<submenu name="Месо и месни продукти" url="/iadene/meso" />
		<submenu name="Тестени продукти" url="/iadene/testeni" />
		<submenu name="Млечни продукти" url="/iadene/mlechni" />
	</menu>
	<menu name="Пиене" url="/piene">
		<submenu name="Бира" url="/iadene/bira" />
		<submenu name="Вино" url="/iadene/vino" />
		<submenu name="Високоалкохолни питиета" url="/iadene/alkohol" />
	</menu>
</menuta>

PHP-парсера с XPath:
<?php
$myxmldoc = simplexml_load_file("hrana-simple.xml");
 
$selectedElements = $myxmldoc->xpath("/menuta/menu");
foreach ($selectedElements as $at){
	echo '<a href="'.$at["url"].'">'.$at["name"]."</a><br />\n";
	foreach ($at->submenu as $subm){
		echo '   <a href="'.$subm["url"].'">'.$subm["name"]."</a><br />\n";
	}
}
?>

Резултата е показан на картинката горе. Много просто и много семпло дървовидно меню за сайт. Изтегляне на кода: hrana_simple.zip

Оценявам високо предложението на koko5 за използването на тези техники. Вече се възползвах от идеите и си спестих ненужни гламутории с MySQL !

anonymous
Вто, 17.08.10, 23:30
@phrozen хвърли един поглед на XSLT и XSLT Example-то
Дано имаш време да направиш и XSLT-пример с обяснения, така, че и аз да ги разбера
stoqncho
Вто, 17.08.10, 23:50

RE: PHP - обхождане на дърво. Нещо патладясах. Help!

” Ха ха ха гледам пуля се и нищо не разбирам баси как могат да се научат тези неща... „
И аз като тебе "Гледам и не вярвам на ушите си". Ти ако намериш от де да ги научиш пиши и аз да разбера.
редактиран от stoqncho на 17.08.10 23:50
electric_cc
Нед, 22.08.10, 15:18
Преди време ми трябваше рекурсивно обхождане на дърво от избрана директория. Намерих това и ми върши чудесна работа. Използвам Visual Basic 6.0. Като компонент се избира Microsoft common controls 6.0. Може да ти помогне като идея.
CreateNode.rar
Изглежда така:

milen
Нед, 22.08.10, 15:59
Здравей @phrozen,
Всъщност в оригиналната ти идея имаше 2 грешки, които и пречеха да работи:

1. Първата грешка беше, че използваш едномерен масив, а не двумерен (масив от масиви) както е необходимо в случая. При това се получава така, че още след дефиницията на масива, част от данните липсват. Например второто срещане като индекс на Food, презаписва първото.

2. Втората грешка беше, че рекурсивното извикване на функцията display трябва да бъде вътре в блока на if-a, а не след него. Когато е след него се получава безкрайна рекурсия.
 
Ето кода:
<?php
 
$ar = array(
	array("", "Food"),
	array("Food", "Fruit"),
	array("Fruit", "Green"),
	array("Green", "Pear"),
	array("Fruit", "Red"),
	array("Red", "Cherry"),
	array("Fruit", "Yellow"),
	array("Yellow", "Banana"),
	array("Food", "Meat"),
	array("Meat", "Beef"),
	array("Meat", "Pork")
);
 
function display($masiv,$rod) {
	echo "<ul>";
	foreach ($masiv as $link){
		list($roditel, $dete) = $link;
		if($roditel == $rod){
			echo "<li> $dete";
			display($masiv, $dete);
		}
	}
	echo "</ul>";
}
 
display($ar, "");
?>

Това е само примерен код, колкото за задача по информатика. Ако реално трябва да работи, трябва да се предвиди възможността данните да са грешни, например да не описват дърво а да има цикъл в тях. Аз в такива случаи си отбелязвам (например в друг масив) обходените клончета, за да се предпазя от зацикляне.

phrozencrew
Нед, 22.08.10, 17:51
milen, благодаря! Включително и за коментарите в темата на incecteater! Доста полезни съвети!
Включвай се по-често във форума, моля!

<1 2 >

Коментар

за нас | за разработчици | за реклама | станете автори | in english  © 1998-2024   Experta Ltd.