Newsgroup: it.comp.www.php
Titolo: ritornare una list mixed

Ho una funzione ricorsiva che usa come valori di ritorno un array di
stringhe e un array di nodi di un DOM document, gli array sono della
stessa lunghezza. Come posso ritornarli nella mia funzione ricorsiva?
 
function recursively_find_text_nodes($dom_element) {
  global $node;
  $return = array();
 
  foreach ($dom_element->childNodes as $dom_child) {
     switch ($dom_child->nodeType) {
	case XML_TEXT_NODE:
	  if (trim($dom_child->nodeValue) !== '') {
			$return[] = $dom_child->nodeValue;
			$node[] = $dom_child;
          }
	break;
	case XML_ELEMENT_NODE:
	  $return = array_merge($return, recursively_find_text_nodes(
$dom_child ));
	break;
     }
   }
   return $return;
}
 
Vorrei fare un return array($return, $node); e poi un list($a, $b) =
recursively_find_text_nodes($dom_element);
 
Quindi un:
$return = array_merge($return, recursively_find_text_nodes( $dom_child ));
===>
modifica di conseguenza.
 
Può funzionare?
-- 
Sandro kensan 
www.kensan.it
 & 
www.qiqi.it
 geek site
Saluto gli agenti della NSA - Hello NSA - 
www.nsa.gov
 


 
Perché non puoi direttamente usare XPath? :)
Questa funzione che deve fare? ;)
 
Ciao!

 Questa funzione che deve fare? ;)
 
Non so molto usare il DOM che è molto utile sapere gestire e quindi sto
facendo pratica esclusivamente col DOM.
 
In generale è utile percorrere tutto l'albero: è l'abc. Nel mio caso si
tratta di trovare tutti i nodi che hanno del testo come foglie. Mi serve
memorizzare sia il testo che il nodo in modo da potere poi modificare il
testo.
 
Ma in generale con le funzioni ricorsive c'è il problema di fare entrare
i dati e di farli uscire e questo è un caso tipico. Chiedo se si può
risolvere.


 
 
Se vuoi linearizzare l'albero come stai facendo va bene. Non vedo a cosa mai
potrebbe servire, però.
 
Ciao!

 potrebbe servire, però.
 
All'atto pratico serve a questo:
 
http://www.kensan.it/articoli/Volantino.php
 
 
La cosa impressionate del php è che ti stupisce. Quello che chiedevo nel
mio primo post ho provato a realizzarlo e funziona! In pratica gli array
con elementi di tipo nodo di un DOM e di tipo string sono possibili. Non
credevo.


 Può funzionare?
 
Se <strike>ti vuoi male</strike> vuoi vivere nel futuro, puoi usare i 
generatori:
 
function find_text_nodes($dom_element)
{
  foreach ($dom_element->childNodes as $dom_child) {
    switch ($dom_child->nodeType) {
      case XML_TEXT_NODE:
        if (trim($dom_child->nodeValue) !== '') {
          yield $dom_child;
        }
        break;
        case XML_ELEMENT_NODE:
          yield from find_text_nodes($dom_child);
	break;
    }
  }
}
 
foreach (find_text_nodes($elem) as $node) {
  ...
}
 
WARNING: codice non testato, scritto di getto, e richiede PHP7. :)
 
Questa versione ha il vantaggio che non tiene in memoria la lista di tutti 
i nodi e del loro contenuto, ma ne genera uno alla volta man mano che li 
consumi, quindi puoi potenzialmente parsare un HTML il doppio più grosso 
con la stessa quantità di RAM.
 
Bye.
 
 

 con la stessa quantità di RAM.
 
Troppo complicato per me...


 
 
E' solo questione d'abitudine. Se vuoi provarci e scriverla con una callback,
vedrai che tutto il codice sarà soprendentemente (dico per te, io già ne sono
sicuro ;)) più chiaro!
 
Ciao!

 
 
Questo secondo me invece è sbagliato. Dovrei fare delle prove per vedere se
ho ragione, ma sono "confident" al 95% :) Scrivo il perché..
 
Come prima cosa, iniziamo a dire che nel caso in oggetto il generatore deve
generare tutto, ovvero non ci sono casi in cui si processa solo una parte di
input.
La domanda quindi è, quanto si risparmia in termini d'occupazione di memoria
per l'array temporaneo, che in un caso (dell'OP) deve essere tutto presente in
memoria e nell'altro può essere riciclato durante il processing.
 
Pensiero 1: in ritorno abbiamo un array dove ogni elemento sono due puntatori
(la stringa e il reference ad un DOMelement, che è un resource): su un 64bit
sono 16byte ad elemento, per (diciamo) 100mila nodi fanno 1.5Mbyte. Come
sappiamo la struttura potrebbe non essere compatta, ma in questo caso l'array
sarebbe memoria contigua, per cui anche considerando gli sprechi e i buchi,
è una quantità comunque troppo irrisoria per farci conti sopra..
 
Pensiero 2: suppongo stiamo usando il GC (altrimenti non avrebbe nemmeno senso
fare questo discorso..). Calcolare quanta memoria è riciclata durante l'uso
d'un generatore è compito arduo, ma in questo caso si può fare un'osservazione
facile: visto che il GC di PHP opera con reference-counting, e visto che il DOM
rimane referenziato mentre gira il generatore, non è possibile riciclare nulla
di quello che effettivamente pesa! L'unico riciclo sarebbe sul riuso della
struttura di cui sopra (quel megabyte e qualcosa).
 
Pensiero 3: per quanto riguarda le performances, sia di memoria che di CPU,
ovviamente sia la soluzione dell'OP che i generatori sono una bestemmia :)
La migliore soluzione è, naturalmente, la classica map (che si emula in PHP con
il passaggio di una callback alla funzione che cicla l'albero).
 
Ciao!

 PHP con il passaggio di una callback alla funzione che cicla l'albero).
 
La soluzione migliore sarebbe un parser alla XMLReader, ma effettivamente 
per file così piccoli stiamo pettinando il pelo sull'uovo. :P
 
Bye.


Ah, fossi stato io avrei usato XPath.. una riga e tutti a casa! ;)
 
Ciao!