:::: MENÚ ::::

Recuperar, editar o borrar nodos del DOM con PHP

Hace unos días terminé un proyecto bastante peculiar, un Spider para capturar los elementos SEM de Google mediante unas determinadas Keywords.

En principio la idea era capturar la página HTML y después buscar en él los etiquetas que quisiera procesar.

La primera opción que se me ocurrió fue usar las expresiones regulares, pero fueron una muy mala elección a la hora de realizar el patrón. Me capturaba más de lo que necesitaba.

La solución la encontré en la clase DOMDocument que ya viene integrada en PHP y que nos proporciona métodos que nos facilita muchísimo la manipulación de un documento HTML o XML.

Si has jugado con JavaScript puro entenderás a la perfección el uso del DOM, pero básicamente y a grandes rasgos el DOM es el árbol de etiquetas de nuestro documento HTML. Puedes encontrar una descripción más extensa en librosweb.es

Antes de empezar, voy a usar para este ejemplo uno de los examples de Bootstrap que guardaré de forma local.

Como con cualquier clase lo primero que haremos será instanciarla. Para cargar el documento HTML usamos loadHTML() o loadHTMLFile(). Con el primero lo cargaremos mediante un string/variable, y el segundo mediante un archivo. Como yo tengo el documento guardado usaré el segundo.

$DOM = new DOMDocument();
$DOM->loadHTMLFile( './example.html' );

Una vez instanciada y cargado nuestro documento HTML, podemos hacer con él lo que queramos, por ejemplo recuperar el contenido de ciertos elementos, modificarlo o crearlos. Para esta pequeña guía, vamos a hacer las tres cosas.

Recuperar el nodo

Si has jugado con JavaScript te resultará muy conocida los siguientes métodos getElementById() y getElementsByTagName(). Nos sirve para campturar el nodo/elemento que le pasamos como argumento. El primero es el ID y el segundo la etiqueta HTML.

Vamos a usar getElementsByTagName(), para ello voy a capturar la etiqueta <h2> y que está repetido varias veces en el pie de la página.

$h2 = $DOM->getElementsByTagName( 'h2' );

Este método nos ha devuelto un nuevo objeto, DOMNodeList, que como su nombre indica, es una lista de nodos.

Para saber si nos ha captura elementos, DOMNodeList nos proporciona una única propiedad que es Length, que es el número de elementos capturados. En nuestro caso son tres.

$h2->length;

Yo voy a cambiar el <h2> del centro (el segundo elemento capturado), pero primero necesito extraerlo de $h2. Voy a usar el método item() del DOMNodeList para recuperarlo.

// Recordad que en programación el primer número es cero.
$h2 = $h2->item( 1 );

En el caso de que deseáramos interactuar con todos los elementos capturados, podríamos usar un for e ir recorriendo uno a uno los elementos. A modo de ejemplo y teniendo los tres elementos anteriores nos quedaría así:

for ( $i=0;$h2->length>$i;$i++ ) {

	$h2->item( $i );

}

Volviendo a lo nuestro. Con la invocación de item() nos devolverá el elemento en un nuevo objeto, DOMNode, con el cual podremos interactuar y seguir jugando.

Modificar el nodo

Dentro de nuestro objecto $h2 tenemos un método llamado setAttribute(), que es para cambiar el valor de un atributo. Como primer argumento el nombre del atributo, y como segundo el valor a asignarle. Lo bueno es que si él detecta que no existe, lo crea y añade el valor que nosotros le especifiquemos.

$h2->setAttribute( 'class', 'text-warning' );

Otra cosa que podemos hacer es cambiar el texto del nodo. Usaremos la propiedad nodeValue y le asignaremos el nuevo texto que queremos.

$h2->nodeValue = 'Modificar el texto';

Añadir nodo

Vamos a añadirle una nueva etiqueta que será <h3> a modo de descripción de nuestro <h2>.

Curiosamente DOMDocument no soporta añadir nodos después, pero si antes, así que si queremos añadir el <h3> como subtítulo, tendremos que dar un rodeo.

Para añadirlo tenemos que usar insertBefore() con el padre del nodo actual, usaremos parentNode con $h2 para saber quien es. Después como argumentos tendremos que decirle el nodo que vamos a añadir (esto lo podemos hacer usando el __constructor() de DOMElement()) y después como segundo argumento nuestra querida <p>, que podemos obtener usando nextSibling en $h2.

En pocas palabras vamos a decirle que queremos añadir un nuevo nodo al papá de <h2>, ante de <p>.

$p = $h2->nextSibling;
$p->parentNode->insertBefore(
	new DOMElement( 'h3', 'Hemos creado un nuevo nodo' ),
	$p
);

Guardar el DOM

Lo último que nos queda es simplemente “guardar”. Para ello recurriremos a nuestro $DOM y usar el método saveHTML(), que nos devolverá el documento HTML con los cambios.

echo $DOM->saveHTML();

Conclusión

Lo bueno de usar DOMDocument es que nos permite recuperar elementos de un documento HTML o XML sin muchas complicaciones, y si partes de la base de JavaScript no te resultará muy difícil de usar.

Además, dispone de XPath para facilitarnos la búsquedas de nodos por tags y atributos.

En resumidas cuentas, si tienes la necesidad de recuperar, modificar o eliminar partes de un documento ya sea en HTML o XML DOMDocument es tu santo grial.

Recuperar, editar o borrar nodos del DOM con PHP

Share on Facebook0Tweet about this on TwitterShare on Google+0Share on LinkedIn4Share on Tumblr0Pin on Pinterest0Email this to someone

  • edgar

    y borrar?

    • Me di cuenta que no lo había escrito unos días más tarde de publicarlo. No he podido dedicarle tiempo a redactarlo porque he tenido más obligaciones.

  • Guillermo Costa

    Hola Ruben!
    Espero me puedas ayudar.
    En index.html tengo un boton, con un ID y un valor (una cadena que representa una coordenada), disparan la apertura de una ventana modal y mediante jquery se carga dentro de esa ventana un archivo x.html que muestra un mapa, antes de mostrar el mapa, necesito contar (dentro de x.html) con la posibilidad de leer con javascript puro o con jquery el valor del boton que disparo el ultimo evento (la apertura de la ventana modal).
    En el index, puedo leer el ID y despues el valor sin problemas, usando
    var varbotonid = $(this).attr(“id”);
    o varbotonid = e.target.id;
    y apartir de ahi, leer el valor de ese elemento.
    Pero como hago lo mismo pero desde x.html?
    Pueden darme un guia?
    Gracias de antemano!

  • Dany MA

    no me dejaba cargar archivos hasta que use esta linea intermediaria

    $DOM = new DOMDocument();
    libxml_use_internal_errors(true);
    $DOM->loadHTMLFile(“index.html”);