1 |
joko |
1.1 |
<? |
2 |
|
|
/** |
3 |
joko |
1.2 |
* This file contains a Data::Lift actor component: |
4 |
|
|
* Data::Lift::hash::topic::EasyTree |
5 |
|
|
* Helper class to negotiate tree node browsing against a remote service. |
6 |
joko |
1.1 |
* |
7 |
|
|
* @author Andreas Motl <andreas.motl@ilo.de> |
8 |
|
|
* @package org.netfrag.glib |
9 |
joko |
1.2 |
* @name Data::Lift::hash::topic::EasyTree |
10 |
joko |
1.1 |
* |
11 |
|
|
*/ |
12 |
|
|
|
13 |
|
|
/** |
14 |
|
|
* Cvs-Log: |
15 |
|
|
* |
16 |
joko |
1.2 |
* $Id: EasyTree.php,v 1.1 2003/04/18 15:49:52 joko Exp $ |
17 |
joko |
1.1 |
* |
18 |
joko |
1.2 |
* $Log: EasyTree.php,v $ |
19 |
|
|
* Revision 1.1 2003/04/18 15:49:52 joko |
20 |
|
|
* initial commit |
21 |
joko |
1.1 |
* |
22 |
|
|
*/ |
23 |
|
|
|
24 |
|
|
/** |
25 |
joko |
1.2 |
* Data::Lift::hash::topic::EasyTree |
26 |
|
|
* |
27 |
|
|
* Helper class to establish tree node browsing |
28 |
|
|
* negotiation against an api of a remote service |
29 |
|
|
* responding with linked lists in XML::Parser::EasyTree |
30 |
|
|
* style. (available on CPAN) |
31 |
|
|
* |
32 |
|
|
* |
33 |
|
|
* [1.] This actor traverses a nested data structure in style of |
34 |
|
|
* CPAN's XML::Parser::EasyTree and translates it into |
35 |
|
|
* a representation which is possible to feed to the |
36 |
|
|
* PEAR::Tree lift actor component. |
37 |
|
|
* "NodeAnchoring" (see below) also occours at this stage. |
38 |
|
|
* |
39 |
|
|
* 2. The PEAR::Tree lift will translate the tree |
40 |
|
|
* to yet another representation which is fed to the |
41 |
|
|
* HTML_TreeMenu Class (also available from PEAR). |
42 |
|
|
* |
43 |
|
|
* 3. This step - you may guess it - is also performed by |
44 |
|
|
* another lift actor: |
45 |
|
|
* It's Data::Lift::object::tree::common::PEAR::HTML::TreeMenu |
46 |
|
|
* and it's worker components TreeMenu::DHTML and TreeMenu::Listbox. |
47 |
|
|
* |
48 |
|
|
* |
49 |
|
|
* By this - and as you may see above - the translation |
50 |
|
|
* process is spawned over three differents steps. |
51 |
|
|
* This may be memory hungry and/or a performance bottleneck. |
52 |
|
|
* Please be aware of this. The implementation gears |
53 |
|
|
* towards clean seperation of all steps required to |
54 |
|
|
* recieve a nested data representation of an xml document |
55 |
|
|
* beeing able to "anchor" each single node. |
56 |
|
|
* |
57 |
|
|
* These "anchors" are made up of XPath filter queries |
58 |
|
|
* which in turn will handle the "DiveIntoNode"-negotiation |
59 |
|
|
* with the backend transparently for your convenience. |
60 |
|
|
* |
61 |
|
|
* The creation/maintenance of the proper "anchor" to access |
62 |
|
|
* while tree traversal is also the job of this class and/or |
63 |
|
|
* its descendants. So be aware of this when mungling |
64 |
|
|
* anything or inheriting from us overwriting methods. |
65 |
|
|
* Most probably it will break behavior at some |
66 |
|
|
* translation step. (If the tree doesn't even break completely, |
67 |
|
|
* but this is what we try to avoid through breaking up the |
68 |
|
|
* translation into some steps) |
69 |
|
|
* TODO: This "Anchoring" should *also* be split up into |
70 |
|
|
* a seperate component. Maybe we could reuse it for |
71 |
|
|
* other data widgets besides trees? |
72 |
|
|
* However - this would be the last stuff required to |
73 |
|
|
* split up the functionality of *this* class into its |
74 |
|
|
* topic parts and should increase stability as well |
75 |
|
|
* when reusing and/or extending this class. |
76 |
|
|
* |
77 |
|
|
* |
78 |
|
|
* If you are interested in "Anchoring" and want to change behavior: |
79 |
|
|
* |
80 |
|
|
* Anchoring is relatively simple. If we arrive at known parts of the |
81 |
|
|
* nested data structure, we just push the appropriate "elements" onto |
82 |
|
|
* the anchor stack. If we "dive out" of this part, we pop the element |
83 |
|
|
* off it. |
84 |
|
|
* The "elements" of the anchor stack are already in XPath syntax |
85 |
|
|
* describing "the node we mean" relatively to the current level. |
86 |
|
|
* |
87 |
|
|
* What's that about? |
88 |
|
|
* It's difficult to map "nodes" orthogonally from the xml document to |
89 |
|
|
* its tree representation. The translator has to decide about how to |
90 |
|
|
* wrap a) the attributes and b) possible childnodes inside the content |
91 |
|
|
* area of each xml tag to a memory data structure representing this |
92 |
|
|
* node. The easiest way to achieve this is by doing oo programming |
93 |
|
|
* and making up (e.g.) a class "Node" having appropriate attributes |
94 |
|
|
* and code to implement its behavior as an arbitrary tree node. |
95 |
|
|
* Multiple instances of a nodes' class make up the tree at runtime. |
96 |
|
|
* |
97 |
|
|
* The problem with this approach is if it comes to the point you |
98 |
|
|
* want to transport your tree via some RPC mechanism, where |
99 |
|
|
* the data structure again has to be serialized somehow. |
100 |
|
|
* How to do that with your object structure? It would require a |
101 |
|
|
* convenient traverse-in, traverse-out api to solve this having |
102 |
|
|
* KISS on every layer. Since the layercount is always increasing |
103 |
|
|
* when trying to achieve some abstract/generic components |
104 |
|
|
* working together in a *flexible* way (regardless of performance |
105 |
|
|
* payoff), the tree should be kept in "simple" linked list style |
106 |
|
|
* troughout the whole translation- and transportation stages. |
107 |
|
|
* |
108 |
|
|
* Otherwise we would mix oo and non-oo stuff at this middleware |
109 |
|
|
* layer and this should be reserved to the very backend side (e.g. |
110 |
|
|
* orm stuff) and the very frontend side (e.g. taglib stuff). |
111 |
|
|
* The middleware just handles non-oo data structures which should |
112 |
|
|
* be easy to rewrite or forward since ... |
113 |
|
|
* It's always just a hash (blessed or not), isn't it? |
114 |
|
|
* |
115 |
|
|
* Assuming this (and there are lists, of course ...) it should be |
116 |
|
|
* possible to translate or echo them in a generic way *without* |
117 |
|
|
* requiring knowledge about each detail of their internal representation. |
118 |
|
|
* |
119 |
|
|
* More detailed layout of the translation: (Perl lingo) |
120 |
|
|
* The tree nodes are automagically vivified at the xml-2-tree |
121 |
|
|
* transformation stage at the remote side through the algorithm |
122 |
|
|
* implemented in {@link XML::Parser::EasyTree}. It follows these rules |
123 |
|
|
* to represent a xml document as a linked list: |
124 |
|
|
* 1. A xml tag (node) is mapped to a hash having |
125 |
|
|
* the keys qw( attrib content name type ). |
126 |
|
|
* 2. Attributes of this tag are wrapped as hashref into 'attrib'. |
127 |
|
|
* 3. Child nodes inside the tag's content area are wrapped as arrayref |
128 |
|
|
* into 'content'. |
129 |
|
|
* 4. 'name' and 'type' are just plain scalars. The former contains the |
130 |
|
|
* tag's name and the latter a type identifier of the tag (one of 'e|.'). |
131 |
|
|
* |
132 |
|
|
* {@link XML::Parser::EasyTree} is written by Eric Bohlman <ebohlman@omsdev.com> |
133 |
|
|
* and acts as a "built-in" style for |
134 |
|
|
* {@link http://search.cpan.org/author/COOPERCL/XML-Parser-2.31/Expat/Expat.pm XML::Parser::Expat} |
135 |
|
|
* similar to XML::Parser::Tree. |
136 |
|
|
* XML::Parser currently has version 2.31 and is |
137 |
|
|
* Copyright (c) 1998-2000 Larry Wall and Clark Cooper. |
138 |
joko |
1.1 |
* |
139 |
|
|
* |
140 |
|
|
* @author Andreas Motl <andreas.motl@ilo.de> |
141 |
|
|
* @copyright (c) 2003 - All Rights reserved. |
142 |
|
|
* @license GNU LGPL (GNU Lesser General Public License) |
143 |
|
|
* |
144 |
|
|
* @link http://www.netfrag.org/~joko/ |
145 |
|
|
* @link http://www.gnu.org/licenses/lgpl.txt |
146 |
|
|
* |
147 |
|
|
* @package org.netfrag.glib |
148 |
|
|
* @subpackage DataLift |
149 |
joko |
1.2 |
* @name Data::Lift::hash::topic::EasyTree |
150 |
joko |
1.1 |
* |
151 |
|
|
* @link http://cvs.netfrag.org/php/libs/org.netfrag.glib |
152 |
|
|
* |
153 |
|
|
*/ |
154 |
|
|
class Data_Lift_hash_topic_EasyTree { |
155 |
|
|
|
156 |
joko |
1.2 |
var $_limit_deepness; |
157 |
|
|
|
158 |
|
|
function perform(&$data) { |
159 |
|
|
|
160 |
|
|
$this->_limit_deepness = 2; |
161 |
|
|
//$this->_limit_listcount = 10; |
162 |
|
|
|
163 |
|
|
//print Dumper($data); |
164 |
|
|
|
165 |
|
|
//array_multisort($data); |
166 |
|
|
//asort($data); |
167 |
|
|
|
168 |
|
|
// TODO: could this initial perform code be revamped into the recursion logic? |
169 |
|
|
|
170 |
|
|
$caption = 'root'; |
171 |
|
|
if ($data[name]) { |
172 |
|
|
$caption = $data[name]; |
173 |
|
|
} |
174 |
|
|
|
175 |
|
|
// push root node to anchor array |
176 |
|
|
//$this->push_anchor('/' . $data[name]); |
177 |
|
|
|
178 |
|
|
// V1 |
179 |
|
|
$data = $this->transform_xml_node($data); |
180 |
|
|
$data = $this->mkContainer( $data, $this->make_tree_node($caption) ); |
181 |
|
|
|
182 |
|
|
//print Dumper($data); |
183 |
|
|
|
184 |
|
|
// V2 |
185 |
|
|
//$data = $this->mkNode('root', $data); |
186 |
|
|
|
187 |
|
|
return $data; |
188 |
|
|
|
189 |
|
|
} |
190 |
|
|
|
191 |
joko |
1.1 |
|
192 |
joko |
1.2 |
function transform_xml_node($xml_node, $atnode = null) { |
193 |
joko |
1.1 |
|
194 |
|
|
//print Dumper($source); |
195 |
joko |
1.2 |
//$this->push_anchor('/' . $xml_node[name]); |
196 |
|
|
|
197 |
|
|
static $level; |
198 |
|
|
$level++; |
199 |
|
|
|
200 |
|
|
if ($level > $this->_limit_deepness) { $level--; return; } |
201 |
|
|
|
202 |
|
|
//print "level: $level" . "<br/>"; |
203 |
joko |
1.1 |
|
204 |
|
|
$buffer = array(); |
205 |
|
|
|
206 |
joko |
1.2 |
foreach ($xml_node as $key => $val) { |
207 |
joko |
1.1 |
|
208 |
joko |
1.2 |
//$this->push_anchor('/' . $key); |
209 |
|
|
|
210 |
|
|
// default node - acts as fallback if not furthermore modified somehow in this loop |
211 |
|
|
//$node = $this->make_tree_node($key, $val); |
212 |
|
|
$node = $this->make_tree_node($key); |
213 |
|
|
|
214 |
|
|
// 1. encapsulate attribute hash into a node container |
215 |
|
|
if ($key && ($key == 'attrib')) { |
216 |
|
|
|
217 |
|
|
// aggregate element keys to build xpq query pointing to the node |
218 |
|
|
$buf = array(); |
219 |
|
|
foreach ($val as $attr_key => $attr_val) { |
220 |
|
|
|
221 |
|
|
// push attribute anchor |
222 |
|
|
$this->push_anchor('[@' . $attr_key . '="' . $attr_val . '"]'); |
223 |
joko |
1.1 |
|
224 |
joko |
1.2 |
$attr_node = $this->make_tree_node($attr_key, $attr_val); |
225 |
|
|
array_push($buf, $attr_node); |
226 |
|
|
|
227 |
|
|
$this->pop_anchor(); |
228 |
|
|
} |
229 |
|
|
$node = $this->mkContainer( $buf, $node ); |
230 |
joko |
1.1 |
|
231 |
joko |
1.2 |
// 2. encapsulate content node |
232 |
|
|
} elseif ($key && ($key == 'content') ) { |
233 |
|
|
|
234 |
|
|
//print Dumper($val); |
235 |
|
|
//$node_name = $val[$key][name]; |
236 |
|
|
|
237 |
|
|
//$this->pop_anchor(); |
238 |
|
|
//$this->push_anchor('/' . $xml_node[name]); |
239 |
|
|
|
240 |
|
|
// transform list of nodes |
241 |
|
|
$nodelist = $this->transform_xml_nodelist($val); |
242 |
|
|
|
243 |
|
|
// propagate this list |
244 |
|
|
$buf = array(); |
245 |
|
|
foreach ($nodelist as $idx => $entry) { |
246 |
|
|
|
247 |
|
|
//print Dumper($entry); |
248 |
|
|
|
249 |
|
|
// build and push anchor |
250 |
|
|
// dive down one level and use the name from there |
251 |
|
|
//$sub_name = '/' . $subnode[name]; |
252 |
|
|
$parent_name = '/' . $val[$idx][name]; |
253 |
|
|
// increase index - XPath counts like humans do. (base=1) |
254 |
|
|
$sub_index = '[' . ($idx + 1) . ']'; |
255 |
|
|
$this->push_anchor($parent_name . $sub_index); |
256 |
|
|
|
257 |
|
|
// numeric indexed array(?) ... |
258 |
|
|
$subnode = $this->make_tree_node($idx); |
259 |
|
|
|
260 |
|
|
// ... encapsulate! |
261 |
|
|
$subnode = $this->mkContainer( $entry, $subnode ); |
262 |
|
|
|
263 |
|
|
//print Dumper($subnode); |
264 |
|
|
|
265 |
|
|
// ... aggregate! |
266 |
|
|
array_push($buf, $subnode); |
267 |
|
|
|
268 |
|
|
// release anchor |
269 |
|
|
$this->pop_anchor(); |
270 |
|
|
} |
271 |
|
|
$node = $this->mkContainer( $buf, $node ); |
272 |
|
|
|
273 |
|
|
//$this->pop_anchor(); |
274 |
|
|
|
275 |
|
|
|
276 |
|
|
// 3. make plain node from key <-> value pair |
277 |
|
|
// These are not the xml-attributes! These are the node-tag names! |
278 |
|
|
} else { |
279 |
|
|
//$this->push_anchor('/' . $key); |
280 |
|
|
$node = $this->make_tree_node($key, $val); |
281 |
|
|
//$this->pop_anchor(); |
282 |
joko |
1.1 |
} |
283 |
joko |
1.2 |
|
284 |
|
|
//$this->pop_anchor(); |
285 |
|
|
|
286 |
|
|
// aggregate all nodes into a flat list at this level |
287 |
|
|
array_push($buffer, $node); |
288 |
joko |
1.1 |
|
289 |
|
|
} |
290 |
|
|
|
291 |
joko |
1.2 |
//$this->pop_anchor(); |
292 |
|
|
|
293 |
|
|
$level--; |
294 |
|
|
|
295 |
joko |
1.1 |
return $buffer; |
296 |
|
|
|
297 |
|
|
} |
298 |
|
|
|
299 |
joko |
1.2 |
function transform_xml_nodelist($xml_nodes) { |
300 |
|
|
$sub_buffer = array(); |
301 |
|
|
foreach ($xml_nodes as $xml_node) { |
302 |
|
|
$this->push_anchor('/' . $xml_node[name]); |
303 |
|
|
array_push($sub_buffer, $this->transform_xml_node($xml_node)); |
304 |
|
|
$this->pop_anchor(); |
305 |
|
|
} |
306 |
|
|
return $sub_buffer; |
307 |
|
|
} |
308 |
|
|
|
309 |
|
|
|
310 |
|
|
function make_tree_node($name, $val = '') { |
311 |
|
|
|
312 |
|
|
// The label of the node, shown to the user. |
313 |
|
|
$caption = $name; |
314 |
|
|
//$filter = $name; |
315 |
|
|
if ($val) { |
316 |
|
|
$caption .= ': ' . $val; |
317 |
|
|
//$filter = $name . '_' . $val; |
318 |
|
|
} |
319 |
|
|
|
320 |
|
|
// The name of the xml-file in this case. |
321 |
|
|
// This is *not* an arbitrary filename - so you *can't* access any file |
322 |
|
|
// on the host which should be considered bad. |
323 |
|
|
// In fact, the names are keys in some subnode table sitting on top of |
324 |
|
|
// a storage handle bundling together some files to a FileSet. |
325 |
|
|
// FIXME: HACK !!! |
326 |
|
|
// Do we already have a Nirvana-API for such things? |
327 |
|
|
// Propagating this through the lift seems impossible... |
328 |
|
|
$identifier = rawurlencode($_GET[ecdid]); |
329 |
|
|
|
330 |
|
|
// A filter expression (XPath lingo) anchoring each node. |
331 |
|
|
//print Dumper($this->_anchors); |
332 |
|
|
//print "anchor: " . join('', $this->_anchors) . '<br/>'; |
333 |
|
|
$anchor = join('', $this->_anchors); |
334 |
|
|
//$filter = $anchor; |
335 |
|
|
$filter = rawurlencode($anchor); |
336 |
|
|
|
337 |
|
|
$parent_filter = rawurlencode(stripslashes($_GET[ecdf])); |
338 |
|
|
//$parent_filter = $_GET[ecdf]; |
339 |
|
|
|
340 |
|
|
// Build proper link arguments to refer to a node as item to let it become view-/editable. |
341 |
|
|
// The identfier (by now the filename) transitions to a meta-argument here |
342 |
|
|
// to make room for the sub-nodename becoming the new identifier. ($name!) |
343 |
|
|
//$link_args = array( ecat => 'item', ecdm => $parent_identifier, ecdf => $filter ); |
344 |
|
|
//$link_args = array( ecat => 'tree', ecdm => $parent_identifier, ecdf => $filter ); |
345 |
|
|
//$link_args = array( ecat => 'tree', ecdm => $parent_identifier, ecdf => $filter, ecdid => $parent_identifier ); |
346 |
|
|
$link_args = array( ecat => 'tree', ecdid => $identifier, ecdf => $filter, ecdm => $parent_filter ); |
347 |
|
|
|
348 |
|
|
$url = url::viewdatanode($name, $link_args); |
349 |
|
|
|
350 |
|
|
// vivify single node |
351 |
|
|
// V1 [2002] |
352 |
|
|
//$node = array( name => $name, attributes => array( url => $url ) ); |
353 |
|
|
// NEW [2003-04-20]: behavior of underlying lift changed |
354 |
|
|
$node = array( name => $caption, link => $url ); |
355 |
|
|
|
356 |
|
|
// TEST: default childnode injection |
357 |
|
|
//$node[children] = array( array( name => '123' ) ); |
358 |
|
|
|
359 |
|
|
return $node; |
360 |
|
|
} |
361 |
|
|
|
362 |
|
|
function mkContainer($data, $parent) { |
363 |
|
|
|
364 |
|
|
/* |
365 |
|
|
print "<hr/>"; |
366 |
|
|
print Dumper($data); |
367 |
|
|
print "<br/>"; |
368 |
|
|
print Dumper($parent); |
369 |
|
|
*/ |
370 |
|
|
|
371 |
|
|
// autocreate parent if undef |
372 |
|
|
//if (!$parent) { $parent = $this->mkNode('dummy'); } |
373 |
|
|
|
374 |
|
|
// sort keys of children alphabetically |
375 |
|
|
// TODO: add behavior to this |
376 |
|
|
//asort($data); |
377 |
|
|
|
378 |
|
|
$p_children = $parent[children]; |
379 |
|
|
$c_children = $data; |
380 |
|
|
|
381 |
|
|
if ($p_children && $c_children) { |
382 |
|
|
//$children = php::array_join_merge($p_children, $c_children); |
383 |
|
|
$children = array_merge($p_children, $c_children); |
384 |
|
|
} else { |
385 |
|
|
$children = $c_children; |
386 |
|
|
} |
387 |
|
|
|
388 |
|
|
// vivify list of children |
389 |
|
|
/* |
390 |
|
|
$node = array( |
391 |
|
|
'children' => $data, |
392 |
|
|
); |
393 |
|
|
*/ |
394 |
|
|
$parent[children] = $children; |
395 |
|
|
|
396 |
|
|
//print "<hr/>"; |
397 |
|
|
//print "parent: " . Dumper($parent) . "<br/>"; |
398 |
|
|
//print "node: " . Dumper($node) . "<br/>"; |
399 |
|
|
|
400 |
|
|
// merge them together and return result |
401 |
|
|
//$result = php::array_join_merge($parent, $node); |
402 |
|
|
//$result = php::array_join_merge($node, $parent); |
403 |
|
|
|
404 |
|
|
//print "result: " . Dumper($result); |
405 |
|
|
//print "<hr/>"; |
406 |
|
|
|
407 |
|
|
//return $result; |
408 |
|
|
return $parent; |
409 |
|
|
} |
410 |
|
|
|
411 |
|
|
function pop_anchor() { |
412 |
|
|
array_pop($this->_anchors); |
413 |
|
|
} |
414 |
|
|
|
415 |
|
|
function push_anchor($anchor) { |
416 |
|
|
if (!is_array($this->_anchors)) { |
417 |
|
|
$this->_anchors = array(); |
418 |
|
|
} |
419 |
|
|
array_push($this->_anchors, $anchor); |
420 |
|
|
} |
421 |
|
|
|
422 |
|
|
|
423 |
|
|
|
424 |
|
|
|
425 |
|
|
|
426 |
|
|
|
427 |
|
|
|
428 |
|
|
function mkNode_old($name, $payload = null) { |
429 |
joko |
1.1 |
|
430 |
|
|
static $level; |
431 |
|
|
static $anchor; |
432 |
|
|
|
433 |
|
|
if (!is_array($anchor)) { $anchor = array(); } |
434 |
|
|
//if (!$caption) { $caption = $name; } |
435 |
|
|
|
436 |
|
|
// TODO: propagate to this place inside some argument container |
437 |
|
|
// (make adjustable from View) |
438 |
joko |
1.2 |
$level_max = 10; |
439 |
joko |
1.1 |
//print "level: $level<br/>"; |
440 |
|
|
|
441 |
|
|
// build url to single node |
442 |
|
|
//$url = linkargs::topic($name); |
443 |
|
|
|
444 |
|
|
|
445 |
|
|
/* |
446 |
|
|
$main_buf = array(); |
447 |
|
|
//for ($i = 0; $i < $level - 1; $i++) { |
448 |
|
|
for ($i = 0; $i <= 2; $i++) { |
449 |
|
|
if (!$anchor[$i]) { continue; } |
450 |
|
|
array_push($main_buf, $anchor[$i]); |
451 |
|
|
} |
452 |
|
|
$main = join('.', $main_buf); |
453 |
|
|
|
454 |
|
|
//$filter = join('.', $anchor); |
455 |
|
|
// FIXME: this is limited to three levels only |
456 |
|
|
//$appendix = $anchor[2] ? (':' . join('.', array( $anchor[2], $anchor[3] ))) : ''; |
457 |
|
|
$appendix = ''; |
458 |
|
|
$appendix_buf = array(); |
459 |
|
|
for ($i = 2; $i <= sizeof($anchor); $i++) { |
460 |
|
|
//for ($i = $level - 1; $i <= sizeof($anchor); $i++) { |
461 |
|
|
if (!$anchor[$i]) { continue; } |
462 |
|
|
array_push($appendix_buf, $anchor[$i]); |
463 |
|
|
} |
464 |
|
|
if ($appendix_buf) { |
465 |
|
|
$appendix = ':' . join('.', $appendix_buf); |
466 |
|
|
} |
467 |
|
|
|
468 |
|
|
//$filter = join('.', array( $anchor[0], $anchor[1] )) . $appendix; |
469 |
|
|
$filter = $main . $appendix; |
470 |
|
|
*/ |
471 |
|
|
|
472 |
|
|
$buf = array(); |
473 |
|
|
for ($i = 0; $i <= $level; $i = $i + 3) { |
474 |
|
|
$part = array(); |
475 |
|
|
for ($j = $i; $j <= $i + 3; $j++) { |
476 |
|
|
if (!$anchor[$j]) { continue; } |
477 |
|
|
array_push($part, $anchor[$j]); |
478 |
|
|
} |
479 |
|
|
array_push($buf, join('.', $part)); |
480 |
|
|
} |
481 |
|
|
$filter = join(':', $buf); |
482 |
|
|
|
483 |
|
|
|
484 |
joko |
1.2 |
if (is_array($payload) && sizeof($payload)) { |
485 |
|
|
|
486 |
|
|
//print "payload: " . Dumper($payload) . "<br/>"; |
487 |
|
|
|
488 |
joko |
1.1 |
// count the tree-level |
489 |
|
|
$level++; |
490 |
|
|
array_push($anchor, $name); |
491 |
|
|
if ($level <= $level_max) { |
492 |
joko |
1.2 |
|
493 |
|
|
//print "payload: " . Dumper($payload) . "<hr/>"; |
494 |
|
|
|
495 |
|
|
// check xml node |
496 |
|
|
$is_xml_node = |
497 |
|
|
php::is_hash($payload) && |
498 |
|
|
isset($payload[attrib]) && |
499 |
|
|
isset($payload[content]) && |
500 |
|
|
isset($payload[type]) && |
501 |
|
|
isset($payload[name]); |
502 |
|
|
|
503 |
|
|
if ($is_xml_node) { |
504 |
|
|
$childnode = $this->transform($payload); |
505 |
|
|
$node = $this->mkContainer($childnode, $node); |
506 |
|
|
|
507 |
|
|
} elseif (is_array($payload) && !php::is_hash($payload)) { |
508 |
|
|
//$childnode = $this->transform_xml_node($payload); |
509 |
|
|
//$node = $this->mkContainer($childnode, $node); |
510 |
|
|
|
511 |
|
|
// make up a virtual xml node |
512 |
|
|
} elseif (php::is_hash($payload)) { |
513 |
|
|
|
514 |
|
|
print "===================== HASH ============<br/>"; |
515 |
|
|
|
516 |
|
|
/* |
517 |
|
|
$data = array( |
518 |
|
|
attrib => array(), |
519 |
|
|
content => $payload, |
520 |
|
|
type => '', |
521 |
|
|
name => 'test2', |
522 |
|
|
); |
523 |
|
|
//$data = $payload; |
524 |
|
|
*/ |
525 |
|
|
|
526 |
|
|
//$childnode = $this->transform($payload); |
527 |
|
|
|
528 |
|
|
/* |
529 |
|
|
$data = array( |
530 |
|
|
name => $node[name], |
531 |
|
|
attributes => array( url => $url ), |
532 |
|
|
//children => array( $payload ), |
533 |
|
|
//children => $this->mkNode('sub', $childnode), |
534 |
|
|
children => array( $this->mkNode('teyt'), $this->mkNode('huhu') ), |
535 |
|
|
); |
536 |
|
|
*/ |
537 |
|
|
|
538 |
|
|
/* |
539 |
|
|
//$childnode = $this->transform(array($payload)); |
540 |
|
|
$childnode = $this->transform($data); |
541 |
|
|
print Dumper($childnode); |
542 |
|
|
|
543 |
|
|
//$node[children] = $childnode; |
544 |
|
|
$node = $this->mkContainer($childnode, $node); |
545 |
|
|
*/ |
546 |
|
|
|
547 |
|
|
//$node = $this->transform($data); |
548 |
|
|
//$node = $data; |
549 |
|
|
|
550 |
|
|
//$node = $this->transform($data); |
551 |
|
|
//$node = $this->mkContainer($childnode, $node); |
552 |
|
|
|
553 |
|
|
|
554 |
|
|
|
555 |
|
|
|
556 |
|
|
//$childnode = $this->transform($data); |
557 |
|
|
//$node2 = array( name => $name, attributes => array( url => $url ) ); |
558 |
|
|
|
559 |
|
|
//$childnode = array( $data ); |
560 |
|
|
//$childnode = $data; |
561 |
|
|
|
562 |
|
|
//$node = $this->mkContainer($data, $node); |
563 |
|
|
//$node = $this->mkContainer($childnode, $node); |
564 |
|
|
|
565 |
|
|
/* |
566 |
|
|
//$node = $this->mkContainer($data, $this->mkNode('node')); |
567 |
|
|
$node[name] = 'hello'; |
568 |
|
|
$node[type] = ''; |
569 |
|
|
$node[attrib] = array(); |
570 |
|
|
$node[content] = array(); |
571 |
|
|
//$node[children] = array( array( name => 'hello' ) ); |
572 |
|
|
$node[children] = array( $data ); |
573 |
|
|
*/ |
574 |
|
|
|
575 |
|
|
//$new = $this->mkNode('acme'); |
576 |
|
|
//$node = $this->mkContainer($new); |
577 |
|
|
|
578 |
|
|
$attribs = array(); |
579 |
|
|
foreach ($payload as $key => $val) { |
580 |
|
|
array_push($attribs, "$key=$val"); |
581 |
|
|
} |
582 |
|
|
$attribs_serialized = join(', ', $attribs); |
583 |
|
|
|
584 |
|
|
//$node[name] = "$name: " . $attribs_serialized; |
585 |
|
|
|
586 |
|
|
//return $childnode; |
587 |
|
|
//$node = $this->mkNode('test', array($payload)); |
588 |
|
|
|
589 |
|
|
//$childnode = $this->mkNode('attributes', $data); |
590 |
|
|
//$subnodes = $this->transform($payload); |
591 |
|
|
//$subnodes = $this->mkNode('attributes', $payload); |
592 |
|
|
//$subnodes = array($payload); |
593 |
|
|
//$childnode2 = $this->mkNode('attributes', $subnodes); |
594 |
|
|
//$childnode = $this->mkContainer($subnodes, $node); |
595 |
|
|
//print "payload: " . Dumper($payload) . "<hr/>"; |
596 |
|
|
//$childnode = $payload; |
597 |
|
|
} |
598 |
|
|
|
599 |
|
|
//$childnode->abc = 'def'; |
600 |
|
|
//print "childnode: " . Dumper($childnode) . "<hr/>"; |
601 |
|
|
/* |
602 |
|
|
if (is_array($childnode)) { |
603 |
|
|
$payload = $this->mkContainer($childnode, $node); |
604 |
|
|
$childnode = $this->transform($payload); |
605 |
|
|
} |
606 |
|
|
*/ |
607 |
joko |
1.1 |
//array_push($buffer, $cnode); |
608 |
|
|
//array_push($buffer, $this->mkContainer(array())); |
609 |
|
|
} |
610 |
|
|
$level--; |
611 |
|
|
array_pop($anchor); |
612 |
|
|
|
613 |
|
|
} else { |
614 |
|
|
// TODO: !! |
615 |
|
|
//$node[attributes][alt] = $name; |
616 |
|
|
//print "no array: " . Dumper($payload) . "<br/>"; |
617 |
|
|
$node[name] = "$name: $payload"; |
618 |
|
|
} |
619 |
|
|
|
620 |
|
|
return $node; |
621 |
|
|
} |
622 |
|
|
|
623 |
|
|
|
624 |
|
|
} |
625 |
|
|
|
626 |
|
|
?> |