phrozencrewВто, 17.08.10, 19:18 | RE: PHP - обхождане на дърво. Нещо патладясах. Help!
Малко старичка тема, но пък полезна. 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! Доста полезни съвети! Включвай се по-често във форума, моля! |