Non so cosa dirti sullo snello, il codice e' molto chiaro ed ordinato.

Il primo appunto che ti faccio e' l' ultimo for: utilizza un dato che sai a priori ciclando tre volte l' array; immagina di volere usare il codice senza sapere a priori il contenuto del dom.

Il secondo appunto e' che ti devi fidare della correttezza del dom: se ci fosse qualche omissione potresti avere i tuoi 5 array con un numero diverso di elementi, avresti di sicuro un errore ma se anche non lo avessi ti ritroveresti con i dati disallineati.

Il terzo piu che un appunto e' un dubbio: non dovresti mettere il controllo if ( !empty($span->nodeValue) ) anche negli altri cicli for?


Per migliorare il tuo codice dovresti fare cosi:
Caricare con DOMXPath in una variabile tutti i nodi <tr> che hanno un child <span> ( anche vuoto )
ciclare su tutti i nodi trovati; in ogni ciclo assegni una variabile con il valore dei 5 attributi che ti servono (xpath dovrebbe consentirti di fare query sul nodo corrente del ciclo)
converti i nulli come preferisci
alla fine di ogni iterazione del ciclo utilizzi le variabili per generare l' output