Enrole o elemento DOM em outro elemento DOM no PHP

Originalmente, fiz uma pergunta nesse sentido usando o Regex, mas foi recomendado o uso da biblioteca PHP DOM ... o que é superior, mas ainda estou travado.

Basicamente, quero agrupar o conteúdo de um<a> em um<span> se ainda não estiver envolto em<span>.

<?php
$input = <<<EOT
<html><head></head>
<body bgcolor="#393a36">
    <a href="#"><span style="color:#ffffff;">Link 1</span></a>
    <a href="#">Link 2</a>
    <a href="#"><img src="mypic.gif" />Image Link</a>
    <a href="#"><u>Underlined Link</u></a>
</body>
</html>
EOT;


$doc = new DOMDocument();
$doc->loadHTML($input);
$tags = $doc->getElementsByTagName('a');
foreach ($tags as $tag) {
    $spancount = $tag->getElementsByTagName("span")->length;
    if($spancount == 0){
        $content = nodeContent($tag);
        $element = $doc->createElement('span');
        $element->setAttribute('style','color:#ffffff;');
        $frag = $doc->createDocumentFragment();
        $frag->appendXML($content);
        $element->appendChild($frag);   
        $tag->nodeValue = ""; //clear node
        $tag->appendChild($element);
    }
}
echo $doc->saveHTML();

function nodeContent($n, $outer=false) { 
    $d = new DOMDocument('1.0'); 
    $d->formatOutput = true;
    $b = $d->importNode($n->cloneNode(true),true); 
    $d->appendChild($b);
    $h = $d->saveHTML(); 
    // remove outter tags 
    if (!$outer) $h = substr($h,strpos($h,'>')+1,-(strlen($n->nodeName)+4)); 
    return $h; 
} 

Ele fornece esta saída:

Aviso do PHP: DOMDocumentFragment :: appendXML (): Entidade: linha 1: erro do analisador: Fim prematuro dos dados na tag img linha 1 em / private / var / folders / 78 / 78vHGigZHcuFeXB1KKJSb ++++ TI / -Tmp- / untitled_3xd. .php na linha 24
Aviso do PHP: DOMDocumentFragment :: appendXML (): Link da imagem em /private/var/folders/78/78vHGigZHcuFeXB1KKJSb++++TI/-Tmp-/untitled_3xd..php na linha 24 Aviso do PHP: DOMDocumentFragment :: appendXML (): ^ in /private/var/folders/78/78vHGigZHcuFeXB1KKJSb++++TI/-Tmp-/untitled_3xd..php na linha 24 PHP Aviso: DOMNode :: appendChild (): o fragmento do documento está vazio em / private / var / folders /78/78vHGigZHcuFeXB1KKJSb++++TI/-Tmp-/untitled_3xd..php na linha 25

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>  
<head></head>  
<body bgcolor="#393a36">  
    <a href="#"><span style="color:#ffffff;">Link 1</span></a>  
    <a href="#"><span style="color:#ffffff;">Link 2</span></a>  
    <a href="#"><span style="color:#ffffff;"></span></a>  
    <a href="#"><span style="color:#ffffff;"><u>Underlined Link</u></span></a>  
</body>  
</html>

Isso funciona principalmente, exceto que é realmente exigente e, como você pode ver, morre se houver umimg (ou similar) dentro doa href.

Qual é a melhor maneira de fazer isso funcionar. Eu tenho batido minha cabeça por um longo tempo embaraçoso agora.

EDITAR

Com base nos comentários abaixo, aqui está o código e a saída revisados. Observe que o texto que precede oimg a tag não está sendo quebrada por algum motivo. Alguma ideia?

$doc = new DOMDocument();
$doc->loadHTML($input);
$tags = $doc->getElementsByTagName('a');
foreach ($tags as $tag) {
    $spancount = $tag->getElementsByTagName("span")->length;
    if($spancount == 0){
    $element = $doc->createElement('span');
    $element->setAttribute('style','color:#ffffff;');
    foreach ($tag->childNodes as $child) {
        $tag->removeChild($child);
        $element->appendChild($child);
    }
    $tag->appendChild($element);

    }
}
echo $doc->saveHTML();

Resultado:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head></head>
<body bgcolor="#393a36">
    <a href="#"><span style="color:#ffffff;">Link 1</span></a>
    <a href="#"><span style="color:#ffffff;">Link 2</span></a>
    <a href="#">Image Link<span style="color:#ffffff;"><img src="mypic.gif"></span></a>
    <a href="#"><span style="color:#ffffff;"><u>Underlined Link</u></span></a>
</body>
</html>

questionAnswers(2)

yourAnswerToTheQuestion