2011-01-13 28 views
7

Estoy tratando de eliminar ciertos enlaces dependiendo de su etiqueta de identificación, pero dejo el contenido del enlace. Por ejemplo, yo quiero convertirPHP Dom Eliminar elemento dejar contenido

Some text goes <a href="http://www.domain.tdl/" id="remove">here</a> 

a

Some text goes here 

He intentado usar el siguiente.

$dom = new DOMDocument; 
$dom->loadHtml(mb_convert_encoding($html, 'HTML-ENTITIES', "UTF-8")); 
$xp = new DOMXPath($dom); 

foreach($xp->query('//a[contains(@id="remove")]') as $oldNode) { 
$revised = strip_tags($oldNode); 
} 

$revised = mb_substr($dom->saveXML($xp->query('//body')->item(0)), 6, -7, "UTF-8"); 
echo $revised; 

más o menos tomados de here pero simplemente escupe el mismo contenido de $html.

¿Alguna idea de cómo lograría esto?

+0

No está modificando su documento aquí, es por eso que escupe el mismo contenido. Ejemplo de que proporcionó llamadas 'replaceChild' en el objeto DOM, y está creando una variable que luego sobrescribirá con una salida de' saveXML' –

+0

Buena pregunta, +1. Vea mi respuesta de una sola solución de expresión XPath que selecciona exactamente los nodos deseados. :) –

Respuesta

12

Esa es mi función para la que:

function DOMRemove(DOMNode $from) { 
    $sibling = $from->firstChild; 
    do { 
     $next = $sibling->nextSibling; 
     $from->parentNode->insertBefore($sibling, $from); 
    } while ($sibling = $next); 
    $from->parentNode->removeChild($from);  
} 

Así que esto:

$dom->loadHTML('Hello <a href="foo"><span>World</span></a>'); 
$a = $dom->getElementsByTagName('a')->item(0); // get first 
DOMRemove($a); 

debe darle:

Hello <span>World</span> 

Para obtener nodos con una identificación específica, utilizar XPath:

$xpath = new DOMXpath($dom); 
$node = $xpath->query('//a[@id="something"]')->item(0); // get first 
DOMRemove($node); 
+0

Eché un vistazo a este código en otra publicación que hice, pero a) Recibo un error 'Error fatal: Llamar a una función de miembro insertBefore() en un no objeto' y b) ¿Cómo adaptar esto a solo elimina los elementos a con una ID específica? – Jack

+0

@Jack: Lo siento, mal, el argumento de la función estaba destinado a ser '$ from' y no' $ node'. Fijo. Gracias por señalar eso. También se agregó un ejemplo para buscar un nodo con un 'id' específico. – netcoder

+0

Dos preguntas; ¿Cómo generaría los datos revisados? Y cuando uso el ejemplo que proporcionó para los ID específicos, recibo el mismo error que antes. – Jack

1

Uso:

//a[@id='remove']/node() 
| 
//*[a[@id='remove']]/node()[not(self::a[@id=''remove])] 

Esto selecciona todos los niños de cualquier a tener atributo id con valor "remove" y todos los hermanos precedentes y siguientes de esta a que no sean en sí otra a tener atributo id con valor de "remove"

2

Un enfoque similar a la respuesta de @ netcoder pero utilizando una estructura de bucle diferente y métodos DOMElement.

$html = '<html><body>This <a href="http://www.domain.tdl/" id="remove">link</a> was removed.</body></html>'; 
$dom = new DOMDocument(); 
$dom->loadHTML($html); 
$xpath = new DOMXPath($dom); 
foreach ($xpath->query('//a[@id="remove"]') as $link) { 
    // Move all link tag content to its parent node just before it. 
    while($link->hasChildNodes()) { 
    $child = $link->removeChild($link->firstChild); 
    $link->parentNode->insertBefore($child, $link); 
    } 
    // Remove the link tag. 
    $link->parentNode->removeChild($link); 
} 
$html = $dom->saveXML(); 
+0

Can '$ child = $ link-> removeChild ($ link-> firstChild);' simplemente se escribe como '$ child = $ link-> firstChild;'? – myol

Cuestiones relacionadas