PDA

Просмотр полной версии : Как создать объект на основе XML-описания его свойств?


iSextuS
30.10.2007, 16:35
Доброго времени суток, уважаемые Знатоки.

Работаю сейчас над флеш версией портфолио а-ля "ЕЖгун (http://zhgun.ru/pics/posters/)". Хочу использовать тот же приём для отображения превьюшек для своих работ. Если вкратце - у меня на сервере лежит папка /portfolio/ с дочерними папками-категориями (Banners, Websites) в каждой из которых размещаются папки-проекты (dir01, dir02 .. dirXX) с описанием проекта, скрином и превьюшкой. внутри папки /portfolio/ сидит мой пхп-скрипт, который выполняет обход вложеных папок и файлов и на их основе формирует XML-описание древа каталогов.

В книге Д.Гурского по AS2.0 в главе посвященной XML была заметка, что для объекта во флеш как на примере ниже можно сгенерировать следующее XML-описание.

пример:
http://sextus.org/wp-content/uploads/2007/sxs2numberone/sheme-gif2.gif


А как можно выполнить обратное действие? то есть на основе XML-описания воссоздать объект в AS2.0?:umnik2:



PS: По задумке, воссоздав объект и перебирая все его свойства циклами, я бы мог по маске передавать пути для загрузки описаний и превьюшек в мой ролик.
например:
"www.mysite.url/ + portfolio/ + banners/ + dir01/ + prev.jpg" // адрес превьюшки для первой работы из папки-категори Banners

- - - дополнительно - - -

моё дерево папок:
http://sextus.org/wp-content/uploads/2007/sxs2numberone/derevo.gif

Cгенерированое скриптом XML-описание этого дерева:
<?xml version="1.0" encoding="utf-8"?>
<portfolio>
<category name="Banners">
<dir01>
<file>full.gif</file>
<file>info.txt</file>
<file>prev.gif</file>
</dir01>
<dir02>
<file>full.gif</file>
<file>info.txt</file>
<file>prev.gif</file>
</dir02>
<dir03>
<file>full.gif</file>
<file>info.txt</file>
<file>prev.gif</file>
</dir03>
</category>
<category name="Websites">
<dir01>
<file>full.gif</file>
<file>info.txt</file>
<file>prev.gif</file>
</dir01>
<dir02>
<file>full.gif</file>
<file>info.txt</file>
<file>prev.gif</file>
</dir02>
<dir03>
<file>full.gif</file>
<file>info.txt</file>
<file>prev.gif</file>
</dir03>
</category>
</portfolio>

PHP-скрипт выполняющий обход:
<?php

ob_start();

echo '<?xml version="1.0" encoding="utf-8"?>';
echo "\n";

function getFile($dir){
$file = opendir($dir);
while($dir = readdir($file)){
if($dir != "." && $dir != ".."){
echo "\t\t<file>".$dir."</file>\n";
}
}
}

function getDir($dir){
$category = opendir($dir);
while($sub_dir = readdir($category)){
if($sub_dir != "." && $sub_dir != ".."){
echo "\t<".$sub_dir.">\n";
getFile($dir.$sub_dir);
echo "\t</".$sub_dir.">\n";
}
}
}

$portfolio = opendir("portfolio/");
echo "<portfolio>\n";
while($dir = readdir($portfolio)){
if(!is_file($dir) && $dir != "." && $dir != ".."){
echo "\t";
echo '<category name="'.$dir.'">';
echo "\n";
getDir("portfolio/".$dir."/");
echo "\t</category>\n";
}
}
echo "</portfolio>";

$str = ob_get_contents();
$fh = fopen("tree.xml", "w"); //необходимо только для отладки работы скрипта;
fputs($fh, $str);
fclose($fh);

ob_flush();

?>

мир вашему дому)

silin
30.10.2007, 17:49
как вариант запихать этот хмл в компонент Tree, по ходу слегка подправив ( нюансы за бортом, но схема рабочая)
зы: можно не править ХМЛ в AS, а заставит пхп генерить сразу валидный вариант
//myTree - компонент Tree на сцене
XML.prototype.ignoreWhite=true;
var dataXML:XML=new XML('<?xml version="1.0" encoding="utf-8"?> <portfolio> <category name="Banners"> <dir01> <file>full.gif</file> <file>info.txt</file> <file>prev.gif</file> </dir01> <dir02> <file>full.gif</file> <file>info.txt</file> <file>prev.gif</file> </dir02> <dir03> <file>full.gif</file> <file>info.txt</file> <file>prev.gif</file> </dir03> </category> <category name="Websites"> <dir01> <file>full.gif</file> <file>info.txt</file> <file>prev.gif</file> </dir01> <dir02> <file>full.gif</file> <file>info.txt</file> <file>prev.gif</file> </dir02> <dir03> <file>full.gif</file> <file>info.txt</file> <file>prev.gif</file> </dir03> </category> </portfolio>');
myTree.labelField="name";
var dataXML:XMLNode=dataXML.firstChild;
setNames(dataXML);
function setNames(node:XMLNode){
if(node.nodeName=="file"){
var textNode:XMLNode=node.firstChild;
node.attributes.name=textNode.nodeValue;
textNode.removeNode();
}else{
if(!node.attributes.name) node.attributes.name= node.nodeName;
var nodes=node.childNodes;
for(var i in nodes){
setNames(nodes[i]);
}
}
}
myTree.dataProvider=dataXML;

iSextuS
31.10.2007, 00:33
Спасибо за ответ, да, разумеется я легко могу избавится от XML-заголовка, и свернуть всё дерево в одну строку для удобства, но насколько я понимаю, (а понимаю я хренова) ваш пример будет формировать несколько иной объект данных. А к большому сожалению структура этого объекта должна быть другой. вот такой:

var portfolio:Object = {Banners:[dir01:[full.gif, info.txt, prev.gif], dir02:[full.gif, info.txt, prev.gif], dir03:[full.gif, info.txt, prev.gif]], Websites:[dir01:[full.gif, info.txt, prev.gif], dir02:[full.gif, info.txt, prev.gif], dir03:[full.gif, info.txt, prev.gif]]}

есть точка отправная (xml) и конечная (пример выше), а вот что между ними должно быть, как конкретно эти вот данные выдрать из XML и присвоить их объекту - я не знаю.

Буду очень благодарен за рабочий пример с подробными комментариями, потому что сам ни в книге, ни в сетевых исходниках решения своей задачи не нашел(( :confused:

silin
31.10.2007, 01:08
iSextuS, я теперь не вполне понимаю в чем проблема..
т.е. отдать дереву хмл - не вопрос, тогда чего:
передать данные из хмл в объект?
нарисовать-настроить все?
'рабочий пример с подробными комментариями' чего вы ждете?
формулируйте вопрос, но чтоб он не был похож на ТЗ, оно тоже проходит, канеш, но в другом разделе :)

iSextuS
31.10.2007, 03:21
блин, да мне просто надо пример, как из хмл-файла вроде моего замутить объект как на примере что я показал ;)

я просто теряюсь - хмл-ка с большим числом вложений, и объект тоже по сути должен быть описан многомерным массивом. - я не знаю как записать все эти данные в объект и правильно распределить их по уровням вложенности)

ну епт - ну как дилетант вроде меня может это вам на пальцах объяснить.(

udaaff
31.10.2007, 04:17
XML без атрибутов:
<root>
<firstChild>
<firstChild>textNode</firstChild>
<secondChild>textNode2</secondChild>
</firstChild>
<secondChild>textNode3</secondChild>
</root>
Обходим следующим методом:
function createObj(currentNode:XMLNode):Object {
if (currentNode.hasChildNodes) {
var currentObj:Object
if (currentNode.firstChild.nodeType == 1) {
currentObj = new Object();
for (var elementNode:XMLNode = currentNode.firstChild; elementNode != null; elementNode=elementNode.nextSibling) {
currentObj[elementNode.nodeName] = arguments.callee(elementNode);
}
} else {
currentObj = currentNode.firstChild.nodeValue;
}
}
return currentObj;
}
Возвращает объект:
{
firstChild: {
firstChild: "textNode",
secondChild: "textNode2"
},
secondChild: "textNode3"
}
XML с атрибутами:
<root>
<firstChild attr="something">
<firstChild>textNode</firstChild>
<secondChild>textNode2</secondChild>
</firstChild>
<secondChild attr="something2">textNode3</secondChild>
</root>
Обходим:
function createObj(currentNode:XMLNode):Object {

var currentObj:Object = new Object();

var attributesObj:Object = new Object();
for (var attr in currentNode.attributes) {
attributesObj[attr] = currentNode.attributes[attr];
}
currentObj.attributes = attributesObj;

if (currentNode.hasChildNodes) {
if (currentNode.firstChild.nodeType == 1) {
for (var elementNode:XMLNode = currentNode.firstChild; elementNode != null; elementNode=elementNode.nextSibling) {
currentObj[elementNode.nodeName] = arguments.callee(elementNode);
}
} else {
currentObj.value = currentNode.firstChild.nodeValue;
}
}
return currentObj;
}
Возвращает объект:
{
firstChild: {
firstChild: {
value: "textNode"
},
secondChild: {
value: "textNode2"
},
attributes: {
attr: "something"
}
},
secondChild: {
value: "textNode3",
attributes: {
attr: "something2"
}
}
}

etc
31.10.2007, 10:25
udaaff, я бы не стал юзать callee там, где можно обойтись без него.

udaaff
31.10.2007, 17:55
Ага, я тоже решил не юзать там, где это возможно из-за того, что она будет вызывать в области видимости объекта arguments, тока забыл уже об этом.

Пример:
class MyClass {

private var length : String ;

public function MyClass() {
length = "SomeSting";
__test(4);
}

private function __test(f : Number) : Void {

trace(length)

if(f > 0) arguments.callee(--f)
}
}

output:

SomeSting
1
1
1
1

iSextuS
01.11.2007, 01:01
udaaff, а последний код разве для AS2?

udaaff
01.11.2007, 01:31
Да, это AS2. Код написан в классе.

etc
01.11.2007, 01:58
Вот, поэтому стоит воздержаться от использования callee там, где можно обойтись без него.

iSextuS
02.11.2007, 01:58
Спасибо земляк