Ver índice
Manipulando ficheros XML desde PHP

        Ocultar índice  

   Índice de contenidos
   Instalación en Windows
   Instalación en Ubuntu
   Servidores seguros
   Páginas dinámicas
   Sintaxis básica
   Operaciones
   Arrays
   Formatos de presentación
   Operadores
   Bucles
   Extraer y ord. información
   Funciones
   Ficheros externos
   Imágenes dinámicas
   Gestión de directorios
   Cookies y sesiones
   Clases y objetos
   Ficheros en formato PDF
   Bases de datos MySQL
   PHP y XML
   PDO - Bases SQLite / MySQL
   MySQL a traves de misqli
   Algo de JavaScript y AJAX


La extensión DOM

La Extension DOM de PHP permite manipular documentos XML mediante las funciones y procedimientos DOM incluidos en una clase de PHP 5 llamada DOMDocument. Esta extensión viene incluida por defecto en PHP y no requiere ninguna modificación del fichero php.ini para ser utilizada.



El DOM (Document Object Model) presenta un documento XML como una estructura de árbol.

Tipos de nodos

Cada uno de los elementos (nodos) que puede contener un documento corresponde a uno de los tipos siguientes:

1 ELEMENT NODE
2 ATTRIBUTE NODE
3 TEXT NODE
4 CDATA SECTION NODE
5 ENTITY REFERENCE NODE
6 ENTITY NODE
7 PROCESSING INSTRUCTION NODE
8 COMMENT NODE
9 DOCUMENT NODE
10 DOCUMENT TYPE NODE
11 DOCUMENT FRAGMENT NODE
12 NOTATION NODE

siendo los verdaderamente útiles para nuestros fines los señalados en rojo en la tabla anterior. Se refieren a los componentes de los documentos XML descritos en la página anterior.

Organización de los nodos

En esta ventana estás visualizando el documento ejemplo474.xml que hemos creado en la página

Los componentes de un documento XML están organizados por niveles de dependencia y dentro de cada uno de esos niveles por items numerados (siempre a partir de cero) según el orden de creación de cada uno de ellos.

Como podrás observar el nivel superior del documento permite un único elemanto con la única excepción de admitir también la inclusión de líneas de comentario.

Por esa razón el comentario que dice: «Después de prólogo...» se identifica como item cero item(0) mientras que el elemento raiz del documento se idenficaría como item(1).

Por otra parte, los elementos de cada nivel se pueden identificar como hijos (childNodes) de un nodo padre (parentNodes). De esta forma, del elemento que contiene el nombre Juan podríamos decir que: es el hijo número uno item(1) del nodo llamado alumno que, a su vez, es el hijo número tres item(3)) de un padre llamado alumnos que es también el tercer hijo item(3))del elemento raíz que es el item señalado con el número uno item(1)) entre los hijos del objeto XML.

Indicada a modo de árbol geneológico, la secuencia: objeto XML -> childNodes ->item(1) -> childNodes ->item(3) -> childNodes ->item(3) -> childNodes ->item(1) nos conduciría hasta el elemento que contiene el valor Juan.

Otra forma de identificar nodos utilizando sus nombres.

objeto XML -> documentElement->getElementsByTagName('alumno')->item(0)->getElementsByTagName('nombre')->item(0)

nos haría el siguiente recorrido. objeto XML->documentElement nos llevaría al nodo raíz del documento. Por medio de getElementsByTagName('alumno') obtendríamos la lista de todos los alumnos contenidos en el documento. A través de item(0) nos situaríamos el el nodo del primero de los alumnos. Por medio de getElementsByTagName('nombre') buscaríamos la lista de hijos del anterior cuyo nombre es nombre. De ellos tomaríamos el primero (en este caso el único) mediante item(0).

La clase DOMDocument

El constructor de la clase DOMDocument creará un objeto utilizando la sintaxis siguiente:

$objeto= new DOMDocument('version','codificacion')

donde $objeto es el identificador del nuevo objeto y donde version y codificacion son dos cadenas opcionales que incluirían respectivamente el número de la versión del nuevo documento XML (actualmente solo es posible la versión 1.0) y el formato de codificación del documento con valores tales como 'utf-8' o ''.

Propiedades de DOMDocument

Los objetos creados por la clase DOMDocument poseen, entre otras, las siguientes propiedades:

encoding

Recoge en una cadena el tipo de codificación del documento tal como se especifica en el prólogo del mismo. Si no hubiera sido establecida el valor de esta propiedad sería una cadena vacía.

xmlVersion

Recoge en una cadena la versión del documento tal como se especifica en el prólogo del mismo. Como ocurría en el caso anterior, si no hubiera sido establecida su valor sería una cadena vacía.

formatOutput

Da formato a la salida aplicando sangrías y espacios extra. Permite valores booleanos (true ó false). Por defecto toma el valor false.

preserveWhiteSpace

Es un valor booleano (TRUE por defecto) que indica si deben mantenerse los espacios redundandes en los contenidos del documento.

nodeType

Esta propiedad no es modificable. Devuelve un número comprendido entre 1 y 12 (son los de la tabla de tipos de nodos incluida más arriba) que se corresponde con el tipo de nodo al que pertenece el objeto actual.

nodeName

Esta propiedad, que tampoco es modificable, contiene el nombre del nodo actual.

nodeValue

En esta propiedad se recoge el valor del contenido del nodo actual. Es modificable de la siguiente forma:

$objeto->nodeValue=nuevo_valor

Métodos de DOMDocument

Algunas de las funciones (métodos) de esta clase son las siguientes:

$objeto->load('fichero');

este método permite incluir en un objeto DOMDocument el contenido de un fichero cuyo nombre y path se especifican en el parámetro fichero.

$raiz=$objeto->documentElement

este método permite recoger en un objeto llamado $raiz el contenido del nodo raíz del objeto XML.

$hijos=$objeto->childNodes

este método permite recoger en un objeto llamado $hijos el conjunto de los nodos hijos del $objeto

$un_hijo=$objeto->childNodes->item(indice)

este método permite recoger en un objeto llamado $un_hijo el nodo hijo del $objeto cuya posicion es señalada por el número indice.

$otro_objeto=$objeto->getElementsByTagName('nombre')

este método crea un objeto $otro_objeto que contiene todos los nodos del objeto $objeto cuyo nombre coincide con nombre.

$otro_elemento=$objeto->getElementsByTagName('nombre')->item(indice)

es una ampliación de caso anterior. Ahora $otro_elemento contiene únicamente el nodo que ocupa la posición señalada por indice en el conjunto de nodos cuyo nombre coincide con nombre.

$otro_elemento=$objeto->getElementsByTagName('nombre')->item(indice)->getElementsByTagName('otro_nombre')->item(otro_indice)

Una nueva ampliación de casos anteriores. Ahora $otro_elemento contiene únicamente el nodo que ocupa la posición señalada por otro_indice en el conjunto de nodos cuyo nombre coincide con otro_nombre y que a la vez son hijos del elemento de índice indice del conjunto formado por los nodos de nombre nombre contenidos en el $objeto. La cadena podría alargarse con nuevas inclusiones.

En este ejemplo puedes ver la forma de acceder a los diferentes nodos de un documento XML.

<?php
/* creamos un objeto DOM con nombre $mi_XML*/
$mi_XML = new DOMDocument();
 /* incluimos el fichero ejemplo474.xml en ese objeto */
$mi_XML->load('ejemplo474.xml');
/* leamos algunas de las propiedades de este objeto */
print "La propiedad encoding vale: ".$mi_XML->encoding."<br>";
print "La propiedad xmlVersion vale: ".$mi_XML->xmlVersion."<br>";
print "La propiedad formatOutput vale: ".$mi_XML->formatOutput."<br>";
print "preserveWhiteSpace vale: ".$mi_XML->preserveWhiteSpace ."<br>";
 print "Como llegar al valor Juan <br><b>";
 print $mi_XML->childNodes->item(1)->childNodes->item(3)->childNodes->item(3)->
                childNodes->item(1)->nodeValue;
 /* para mayor comodidad podríamos haber creado un objeto de esta forma: */
$juanito=$mi_XML->childNodes->item(1)->childNodes->item(3)->childNodes->item(3)->childNodes->item(1);
/* al imprimir el valor de la propiedad nodeValue  del nuevo objeto
   dará el mismo resultado que en el caso anterior */
 print "</b><br />también así se llega: ".$juanito->nodeValue;
 print "</b><br />Otra forma de llegar: ";
print $mi_XML->documentElement->getElementsByTagName('alumno')->item(0)->
             getElementsByTagName('nombre')->item(0)->nodeValue;
/*$mi_XML->documentElement nos llevaría al nodo raíz. getElementByTagName('alumno') nos daría
  los nodos   (contenidos en el raiz) que tienen por nombre alumno. El item(0) que le sigue
  indicaría que vamos al primero de los nodos alumno y allí mediante getElementsByTagName('nombre')
  buscaríamos el array que contiene   los elementos nombre de ese alumno concreto.
  Como solo hay un nombre estará identificado por el índice 0 (item(0))
  y de este ya extraeríamos el valor */

print "</b><br>Vamos a conocer el nombre del nodo padre de Juan:<br><b>";
print $juanito->parentNode->nodeName;
print "</b><br>Vamos a conocer el nombre del nodo abuelo de Juan:<br><b>";
print $juanito->parentNode->parentNode->nodeName;
print "</b><br />El bisabuelo de Juan se llama:<br><b>";
print $mi_XML->childNodes->item(1)->childNodes->item(3)->childNodes->item(3)->childNodes->item(1)->
         parentNode->parentNode->parentNode->nodeName;
print "</b><br />¿Tendrá Juan tatarabuelo ?<br><b>";
print $juanito->parentNode->parentNode->parentNode->parentNode->nodeName."</b>";
/* creemos un nuevo objeto con nombre $hijuela */
$hijuela=$mi_XML->childNodes->item(1)->childNodes->item(3)->childNodes->item(7)->childNodes->item(7);
/* visualizemos las propiedades del nuevo objeto */
print "<br><i>El nodo se llama </i> ".$hijuela->nodeName;
print " <i>es del tipo:</i> ".$hijuela->nodeType;
print " y <i>contiene esto</i>: ".$hijuela->nodeValue;
?>
Ejecutar el script

Crear documentos XML mediante la clase DOMDocument

La creación de documentos XML por medio de la clase DOMDocument requiere la utilización de algunos métodos aún no descritos. Son los siguientes:

$elemento = $objeto->createElement('nombre','contenido');

Recoge en $elemento un nuevo elemento del $objeto asignándole el nombre e incluyendo como contenido especificado en la cadena contenido. Si no se especifica esta última tomará por defecto el valor de una cadena vacía.

$comentario = $objeto->CreateComment('texto');

Recoge en $comentario un nuevo comentario del $objeto incluyendo como contenido especificado en la cadena texto.

$cdata = $objeto->createCDATASection('texto');

Recoge en $cdata un nuevo elemento (del tipo CDATA) del $objeto incluyendo como contenido especificado en la cadena texto.

  ¡Cuidado!  

Los métodos crean el elemento, el comentario o el CDATA pero no lo incluye en el documento XML. Para esto es necesario recurrir a los métodos que se incluyen a continuación.

$objeto->(.. nodos)->appendChild($elemento);
$objeto->(.. nodos)->appendChild($comentario);
$objeto->(.. nodos)->appendChild($cdata);

Incluyen en el nivel indicado por $objeto->(.. nodos) un nuevo elemento, comentario o CDATA que han de ser creados mediante los métodos Create... descritos anteriormente.

$objeto->insertBefore($nuevo_elemento, $otro_elemento);

Incluye un elemento $nuevo_elemento precediendo a $otro_elemento incluido como segundo parámetro.

$objeto->insertBefore($nuevo_elemento, $otro_elemento->nextSibling);

Incluye $nuevo_elemento en el mismo nivel y a continuación del del $otro_elemento que precede los caracteres obligatorios ->nextSibling.

$objeto->(.. nodos)->AddAttribute(atributo, valor);

Añade un nuevo atributo al elemento $objeto->(.. nodos) y le asigna el valor indicado por valor.

$objeto->(.. nodos)->->setAttribute(atributo, valor);

Modifica el valor del atributo correspondiente al elemento $objeto->(.. nodos).

$lectura= $objeto->(.. nodos)->->getAttribute(atributo, valor);

Recoge en la variable $lectura el valor del atributo correspondiente al elemento $objeto->(.. nodos).

$objeto->saveXML();

Recoge en una cadena el árbol de contenidos XML del objeto $objeto. Resulta muy útil para visualizar los contenidos y formatos de los documentos XML con los que estamos trabajando.

$objeto->save('fichero');

Permite guardar en un fichero cuyo path, nombre y extensión se indica en el parámetro fichero el contenido del objeto $objeto.

En este ejemplo incluimos las diferentes opciones de uso de estos métodos para crear un documento XML.

<?php
header("content-type: text/xml");
/* Empezamos incluyendo una cabecera que especifica el tipo de documento resultante de la ejecución
   de este script. Será text/xml. De esta forma los navegadores, IE, Firefox y Opera nos permitirán
   ver la estructura del documento.

   Creamos un nuevo objeto DOMDocument en cuyo prólogo incluiremos la versión de XML (1.0)
   y la forma de codificación (utf8) dentificaremos el objeto mediante el nombre \$mi_XML */
$mi_XML = new DOMDocument('1.0','utf-8');
/* Las propiedades $mi_XML->encoding habrá tomado el valor utf-8.
   y $mi_XML->xmlVersion tendrá como valor 1.0
   $mi_XML->formatOutput toma por defecto el valor false,
   podemos modificar esa propiedad (a true) con: */
$mi_XML->formatOutput=true;
/* La propiedad $mi_XML->preserveWhiteSpace  toma true por defecto.
 Podriamos cambiarla a false de la forma siguiente: */
 $mi_XML->preserveWhiteSpace=false;
/* Creado el preámbulo del objeto $mi_XML el paso siguiente sería crear los diferentes elementos
   que lo componen.
   El elemento raiz de nuestro esquema se llama es profesores. Lo creamos de la siguiente forma: */
$raiz=$mi_XML->CreateElement('profesores');
/* Debemos añadirlo como un hijo (Child) del objeto principal */
$mi_XML->appendChild($raiz);
/* vamos a agregar algunod de comentarios. Empezamos por crearlos */
$c1=$mi_XML->CreateComment('Voy fuera de profesores');
$c2=$mi_XML->CreateComment('Voy dentro de profesores');
$c3=$mi_XML->CreateComment('Quiero ser el primero');
$c4=$mi_XML->CreateComment('Quiero ponerme antes de los profes');
$c5=$mi_XML->CreateComment('Me insertarán de otra forma');
/* los insertamos (lo importante es donde) El primer comentario será
 un hijo del objeto principal  y se insertará detrás del último de
 los ya insertados (detrás del elemento profesores en este caso*/
$mi_XML->appendChild($c1);
/* este comentario iría dentro del elementos profesores ya que $raiz
   es la variable sobre la que fue creado el elemento profesores  */
$raiz->appendChild($c2);
/* colocaremos a hora $c3 en primera posicion mediante insertBefore */
$mi_XML->insertBefore($c3,$raiz);
/* el comentario $c4 lo vamos a colocar justamente detras de $c3
  $c3 "seré el siguiente hermano de $c3" */
$mi_XML->insertBefore($c4,$c3->nextSibling);
$mi_XML->getElementsByTagName('profesores')->item(0)->appendChild($c5);
/* crearemos un nuevo elemento (profe) */
$un_profe=$mi_XML->CreateElement('profe');
/* lo insertamos dentro de del nodo $raiz (profesores) */
$raiz->appendChild($un_profe);
/* iremos añadiendo a este profe recien creado los  diferentes elementos
segun el diseño del gráfico del organigrama */
$un_profe->setAttribute('situacion',utf8_encode("Func en practicas"));
$p1=$mi_XML->CreateElement('nombre','Antonio');
$p2=$mi_XML->CreateElement('apellidos','López del Río');
$un_profe->appendChild($p1);
$mi_XML->getElementsByTagName('profe')->item(0)->appendChild($p2);
$mi_XML->getElementsByTagName('profe')->item(0)->setAttribute('sexo',"varon");
$p3=$mi_XML->CreateElement('nacimiento','21-01-1978');
$p3->setAttribute('zodiaco','Acuario');
$un_profe->appendChild($p3);
/* ahora va la retribución */
$p4=$mi_XML->CreateElement('retribucion');
$p4->setAttribute('IRPF','15 %');
$p4->setAttribute('sexenios','5');
$p5=$mi_XML->CreateElement('base');
$p6=$mi_XML->CreateElement('complemento');
$p5t=$mi_XML->createTextNode('1678,32 €');
$p6t=$mi_XML->createTextNode('1678,32 €');
$un_profe->appendChild($p4);
$p4->appendChild($p5);
$p4->appendChild($p6);
$p5->appendChild($p5t);
$p6->appendChild($p6t);
$p7=$mi_XML->CreateElement('valoracion');
$cdata =$mi_XML->createCDATASection("Inspección día 23/08/1998\n Llega tarde y sin corbata");
$p7->appendChild($cdata);
$un_profe->appendChild($p7);
/* agregado masivo de datos a partir de arrays que pueden proceder
de la lectura de una base de datos */
$nombres=array('Juan','Perico','Andres','Dolores','Rosario','Alejandra');
$apellidos=array('Fernández González','Ruíz del Olmo','García García','Díaz Alonso',
    'Carbajal Berrocal','Altamira del Busto');
$sexos=array('Varon','Varon','Varon','Hembra','Hembra','Hembra');
$situaciones=array ('Catedrático','Profesor','Interino','Interina','Catedrática','Profesora');
$nacimiento=array('14-12-1967','21-02-1981','23-04-1978','16-06-1967','05-08-1981','03-10-1987');
$signo=array('Aries','Acuario','Libra','Tauro','Sagitario','Cancer');
$sueldo_base=array('1.247,32 €','1.257,22 €','1.217,02 €','1.307,20 €','2.047,95 €','1.300,00 €');
$complementos=array('1.300 €','1.124 €','1.800 €','1.417 €','1.632 €','1.497 €');
$irpf=array('13%','12%','23%','21%','18.5%','11%');
$sexenios=array(1,2,3,4,5,6);
$valoracion=array('Excelente profesional','Manifiestamente mejorable','Necesita reciclaje',
   'Impecable','Excepcional','Promete grandes éxitos');

$cuenta=$mi_XML->getElementsByTagName('profe')->length;
for ($i=0;$i<sizeof($nombres);$i++){
        $un_profe=$mi_XML->CreateElement('profe'); 
        $raiz->appendChild($un_profe);
        $un_profe->setAttribute('situacion',$situaciones[$i]);
        $p1=$mi_XML->CreateElement('nombre',$nombres[$i]);
        $p2=$mi_XML->CreateElement('apellidos',$apellidos[$i]);
        $un_profe->appendChild($p1);

        $mi_XML->getElementsByTagName('profe')->item($i+$cuenta)->appendChild($p2);
        $mi_XML->getElementsByTagName('profe')->item($i+$cuenta)->setAttribute('sexo',$sexos[$i]);

        $p3=$mi_XML->CreateElement('nacimiento',$nacimiento[$i]);
        $p3->setAttribute('zodiaco',$signo[$i]);
        $un_profe->appendChild($p3);
        $p4=$mi_XML->CreateElement('retribucion');
        $p4->setAttribute('IRPF',$irpf[$i]);
        $p4->setAttribute('sexenios',$sexenios[$i]);
        $p5=$mi_XML->CreateElement('base');
        $p6=$mi_XML->CreateElement('complemento');
        $p5t=$mi_XML->createTextNode($sueldo_base[$i]);
        $p6t=$mi_XML->createTextNode($complementos[$i]);
        $un_profe->appendChild($p4);
        $p4->appendChild($p5);
        $p4->appendChild($p6);
        $p5->appendChild($p5t);
        $p6->appendChild($p6t);
        $p7=$mi_XML->CreateElement('valoracion');
        $cdata =$mi_XML->createCDATASection($valoracion[$i]);
        $p7->appendChild($cdata);
        $un_profe->appendChild($p7);
}

echo $mi_XML->saveXML();
$mi_XML->save('ejemplo478.xml');
?>
Ejecutar el script Ver documento XML

Como muestra de cual es el procedimiento para interpretar y reconocer los valores de los nodos de un documento hemos incluido este ejemplo.

Ejemplo481.php Ver código fuente

Extraer datos de un fichero XML

En la página anterior veíamos un ejemplo de como confeccionar un documento XML partiendo de los contenidos en una tabla MySQL. En este ejemplo veremos algunas opciones para efectuar el proceso inverso. Partiendo del documento XML que hemos elaborado en el ejemplo anterior recogeremos en variables PHP los contenidos de aquel documento.

<?php
/* creamos un nuevo objeto y cargamo el fichero XML creado en el ejemplo anterior */
$mi_XML = new DOMDocument();
$mi_XML->load('ejemplo478.xml');
/* determinamos el numero de nodos con nombre "profe" */
$numero_profes=$mi_XML->getElementsByTagName('profe')->length;
/* creamos nuevos objetos que contenga los nodos con los diferentes nombres
Esta manera de hacerlo puede plantear un problema. De haber otros nodos, por ejemplo
alumnos que contuvieran nombres o apellidos los recogeria todos sin discriminar a que
nodo padre pertenecen */
$los_profes=$mi_XML->getElementsByTagName('profe');
$los_nombres=$mi_XML->getElementsByTagName('nombre');
$los_apellidos=$mi_XML->getElementsByTagName('apellidos');
$el_nacimiento=$mi_XML->getElementsByTagName('nacimiento');
$la_retribucion=$mi_XML->getElementsByTagName('retribucion');
$la_base=$mi_XML->getElementsByTagName('base');
$el_complemento=$mi_XML->getElementsByTagName('complemento');
$la_valoracion=$mi_XML->getElementsByTagName('valoracion');
/* recorremos el bucle de los diferentes objetos extrayendo sus valores
mediante nodeValue en el caso de nodos y por medio de getAttribute en
el caso de los atributos. Vamos recogiendo los diferentes valores
en arrays escalares */
for ($i=0;$i<$numero_profes;$i++){
        $sexo[]=$los_profes->item($i)->getAttribute('sexo');
        $situacion[]=$los_profes->item($i)->getAttribute('situacion');
        $nombre[]=$los_nombres->item($i)->nodeValue;
        $apellidos[]=$los_apellidos->item($i)->nodeValue;
        $nacimiento[]=$el_nacimiento->item($i)->nodeValue;
        $zodiaco[]=$el_nacimiento->item($i)->getAttribute('zodiaco');
        $base[]=$la_base->item($i)->nodeValue;
        $irpf[]=$la_retribucion->item($i)->getAttribute('IRPF');
        $sexenios[]=$la_retribucion->item($i)->getAttribute('sexenios');
        $complemento[]=$el_complemento->item($i)->nodeValue;
        $valoracion[]=$la_valoracion->item($i)->nodeValue;
}
/* insertamos el encabezado de una tabla para presentar los resultados que
también podrían ser utilizados para crear una tabla en MySQL o para cualquier
otro proposito en el que se manejen variables PHP */
?>
<table>
<tr style="font-size:10px"><td>Nombre</td><td>Apellidos</td>
<td>Sexo</td><td>Situación</td><td>Fecha nacimiento</td>
<td>Zodiaco</td><td>Sueldo base</td><td>Complementos</td>
<td>IRPF</td><td>Sexenios</td><td>Valoración</td></tr>
<?php
  /*mediante este bucle creamos las sucesivas filas de la tabla */
for ($i=0;$i<sizeof($nombre);$i++){
  print "<tr style='font-size:10px'><td>".$nombre[$i]."</td>";
  print "<td>".utf8_decode($apellidos[$i])."</td><td>".$sexo[$i]."</td>";
  print "<td>".utf8_decode($situacion[$i])."</td><td>".$nacimiento[$i]."</td>";
  print "<td>".$zodiaco[$i]."</td><td>".utf8_decode($base[$i])."</td>";
  print "<td>".utf8_decode($complemento[$i])."</td><td>".$irpf[$i]."</td>";
  print "<td>".$sexenios[$i]."</td><td>".utf8_decode($valoracion[$i])."</td></tr>";
}
print "</table><br /><br /><br />";
/* como opción alternativa para extraer los mismos valores asegurándose que
no se incluyen más que los correspondientes a los profesores podemos extraerlos
del nodo profes. Extraemos los atributos de cada uno de los objetos profe (sexo y situación)
y los demás valores los extraemos siempre del item(0) ya que el objeto nombre es hijo (único)
de profes */
$prof=$mi_XML->getElementsByTagName('profe');
for ($i=0;$i<$numero_profes;$i++){
  $n_sexo[]=$prof->item($i)->getAttribute('sexo');
  $n_situacion[]=$prof->item($i)->getAttribute('situacion');
  $n_nombre[]=$prof->item($i)->getElementsByTagName('nombre')->item(0)->nodeValue;
  $n_apellidos[]=$prof->item($i)->getElementsByTagName('apellidos')->item(0)->nodeValue;
  $n_nacimiento[]=$prof->item($i)->getElementsByTagName('nacimiento')->item(0)->nodeValue;
  $n_zodiaco[]=$prof->item($i)->getElementsByTagName('nacimiento')->item(0)->getAttribute('zodiaco');
  $n_base[]=$prof->item($i)->getElementsByTagName('base')->item(0)->nodeValue;
  $n_irpf[]=$prof->item($i)->getElementsByTagName('retribucion')->item(0)->getAttribute('IRPF');
  $n_sexe[]=$prof->item($i)->getElementsByTagName('retribucion')->item(0)->getAttribute('sexenios');
  $n_complemento[]=$prof->item($i)->getElementsByTagName('complemento')->item(0)->nodeValue;
  $n_valoracion[]=$prof->item($i)->getElementsByTagName('valoracion')->item(0)->nodeValue;

}
/* repetimos el proceso anterior con un pequeño cambio.
Durante la codificación/decodificación del símbolo del euro
hemos perdido ese carácter que ahora aparece sustituido por un signo de interrogación.
 str_replace nos permite corregir  esa deficiencia visual
 tal como puedes ver si comparas las dos tablas resultantes de la ejecución de este script */
?>
<table>
<tr style="font-size:10px"><td>Nombre</td><td>Apellidos</td>
<td>Sexo</td><td>Situación</td><td>Fecha nacimiento</td>
<td>Zodiaco</td><td>Sueldo base</td><td>Complementos</td>
<td>IRPF</td><td>Sexenios</td><td>Valoración</td>
<?php 
for ($i=0;$i<sizeof($nombre);$i++){
  print "<tr style='font-size:10px'><td>".$n_nombre[$i]."</td>";
  print "<td>".utf8_decode($n_apellidos[$i])."</td><td>".$n_sexo[$i]."</td>";
  print "<td>".utf8_decode($n_situacion[$i])."</td><td>".$n_nacimiento[$i]."</td>";
  print "<td>".$n_zodiaco[$i]."</td><td>".str_replace('?', '€', utf8_decode($n_base[$i]))."</td>";
  print "<td>".str_replace('?', '€', utf8_decode($n_complemento[$i]))."</td><td>".$n_irpf[$i]."</td>";
  print "<td>".$n_sexe[$i]."</td><td>".utf8_decode($n_valoracion[$i])."</td></tr>";
}
print "</table><br /><br /><br />";
?>
Ejecutar el script

Importar datos de XML a otro XML

Además de los métodos descritos anteriormente disponemos de:

$objeto->importNode(nodo_a_importar, boleano);

Agrega al objeto actual el contenido del objeto nodo_a_importar. La opción booleano debe tener el valor TRUE cuando se pretenda importar los atributos junto con los elementos del nodo.

Este ejemplo es una pequeña muestra de las posibilidades que ofrece PHP para la modificación de los contenidos de ficheros XML.

<?php
header ("content-type: text/plain");
/* creamos dos objetos uno llamado importador que será el que recoja
los datos de un documento preexistente y mi_XML que será el objeto
que contendrá el nuevo fichero */
$importador = new DOMDocument();
$mi_XML = new DOMDocument('1.0','utf-8');
/* cargamos el documento ejemplo478.xml completo */
$importador->load('ejemplo478.xml');
/* extraemos el objeto raiz llamado profesores y objeto único,
por eso el item(0))(olvidando líneas de comentario del orginal)
y lo ponemos en un objeto nuevo llamado colocar */
$colocar = $importador->getElementsByTagName("profesores")->item(0);
/* el objeto mi_XML aun no contiene nada asi que crearemos un nuevo objeto
y se lo agregaremos. Al ser el primer elemento será el elemento raiz del nuevo documento*/
$nueva_raiz=$mi_XML->CreateElement('plantilla_completa');
$mi_XML->appendChild($nueva_raiz);
/* insertamos los elementos extraidos del fichero importado que habíamos
recogido en una variable llamada colocar */
$agregar = $mi_XML->importNode($colocar, true);
/* colocamos el nuevo objeto agregar como hijo de la raiz de documento */
$nueva_raiz->appendChild($agregar);
/*añadimos un nuevo atributo al elemento profesores (unico, era el raiz del fichero
que acabamos de importar) */
$mi_XML->getElementsByTagName("profesores")->item(0)->setAttribute('nivel','Secundaria');
/*creamos un objeto con con datos del profesores del nodo importador repitiendo
lo que hemos hecho conaterioridad */
$extraer = $importador->getElementsByTagName("profesores")->item(0);
/* importamos el nodo completo */
$agregar = $mi_XML->importNode($extraer, true);
/* insertamos nuevamente el nodo profesores recogido previamente en el objeto agregar */
$nueva_raiz->appendChild($agregar);
/* asignamos al nodo profesores recien creado item(1) el atributo nivel */
$mi_XML->getElementsByTagName("profesores")->item(1)->setAttribute('nivel','Primaria');
/* creamos un objeto primarios que contiene todos los elementos profe de estos ultimos profesores */
$primarios=$mi_XML->getElementsByTagName("profesores")->item(1)->getElementsByTagName("profe");
/* modificamos el atributo situación de los profes de primarios */
for($i=0;$i<$primarios->length;++$i){
  $cambiar=$primarios->item($i)->getAttribute('situacion');
   switch ($cambiar){
        case "Catedrática":
            $primarios->item($i)->setAttribute('situacion','Profesora de Segundo Ciclo');
            break;
        case "Profesor":
            $primarios->item($i)->setAttribute('situacion','Profesor de Primer Ciclo');
            break;
        case "Profesora":
            $primarios->item($i)->setAttribute('situacion','Profesora de Primer Ciclo');
            break;
        case "Catedrático":
            $primarios->item($i)->setAttribute('situacion','Profesor de Segundo Ciclo');
        break;
   }
 }
 /* vamos a modificar datos de nombres y apellidos para evitar los duplicado consecuencia
    de haber importado dos veces el mismo nodo */
 $nuevos_apellidos=array('Alonso Galguera','Ruíz de Alda','Alonso Aller',
         'Menéndez López','García Uría','Alvarez del Campo','Feito Parrondo');
 $nuevo_nombre=array ('Luis','Eduardo','Fernando','Gonzalo','Carmela',
                     'Luisa','Servanda');
 /* recorremos los elementos primarios cambiando el valor de los nodos nombre (con item0 por tener
 solo un elemento) por el nuevo nombre  y los apellidos por lo nuevos apellidos
 y además hacemos una sustitución de la valoración en el caso de producirse una coincidencia */
for($i=0;$i<$primarios->length;++$i){
    $primarios->item($i)->getElementsByTagName("nombre")->item(0)->nodeValue=$nuevo_nombre[$i];
    $primarios->item($i)->getElementsByTagName("apellidos")->item(0)->
                               nodeValue=utf8_encode($nuevos_apellidos[$i]);
    if($primarios->item($i)->getElementsByTagName("valoracion")->item(0)->
                                                    nodeValue=="Necesita reciclaje"){
        $primarios->item($i)->getElementsByTagName("valoracion")->item(0)
            ->firstChild->nodeValue=utf8_encode("Además de reciclaje\n necesita un milagro");
    }
        /* quitamos el atributo zodiaco a todos profes de primara */
    $primarios->item($i)->getElementsByTagName("nacimiento")->item(0)->removeAttribute('zodiaco');
    /* quitamos el atributo sexenios a todos aquellos cuya situación empiece por Inter */
    if(substr($primarios->item($i)->getAttribute("situacion"),0,5)=="Inter"){
        $primarios->item($i)->getElementsByTagName("retribucion")->item(0)->removeAttribute('sexenios');
    }
}
 /*Busco a Servanda le cambio el nombre por  Severina*/
for($i=0;$i<$primarios->length;++$i){
      $nombre=$primarios->item($i)->getElementsByTagName("nombre")->item(0)->nodeValue;
         if ($nombre=="Servanda"){
            $primarios->item($i)->getElementsByTagName("nombre")->item(0)->nodeValue="Severina";
         }
}
      /* visualizamos los resultados */
echo $mi_XML->saveXML();
?>
Ejecutar el script