08 Septiembre 2010
He aquí unas funciones que me he hecho para manejarme con el xml (basadas en simplexml).
Leer xml: Sirve para leer un código xml de un fichero
<?php
function leer_xml($fichero){
//Comprobamos que existe el fichero
if (file_exists($fichero)) {
//Lo cargamos como objeto con simplexml
$dom = simplexml_load_file($fichero);
}
else{
echo 'Fallo al abrir '.$fichero.'<br/>';
$dom = -1;
}
if(!$dom) return -1;
return $dom;
}
?>
Una alternativa sería para leer xml desde una variable:
<?php
function leer_xml ( $xml ){
//Comprobamos que existe la variable
if ( $xml ) {
//Lo cargamos como objeto con simplexml
$dom = simplexml_load_string ( $xml );
}
else{
echo 'Fallo al leer el código<br/>' ;
$dom = - 1 ;
}
if(! $dom ) return - 1 ;
return $dom ;
}
?>
Función insertar_nodo: Añade un nodo/hijo a la estructura xml
<?php
function insertar_nodo ( $nodo , $datos , $fichero , $duplicar , $duplicados ){
//Leemos fichero
if(( $xml = leer_xml ( $fichero )) == - 1 ) return - 1 ;
//Comprobamos si puede haber nodos duplicados o no y si los hay
if( $duplicar == 0 ) $stop = buscar_nodo ( $nodo , $duplicados , $fichero );
else $stop = 0 ;
//Si no hay nodos duplicados o si puede haberlos, seguimos
if( $stop == 0 ){
//Guardamos todos los datos en un nuevo nodo
$tag = $xml -> addChild ( $nodo );
foreach( $datos as $valor ) $tag -> addChild ( $valor [ 'tag' ], $valor [ 'dato' ]);
//Guardamos el fichero
$xml -> asXML ( $fichero );
}
return 0 ;
}
?>
Buscar nodo: Busca dentro de los nodos de un xml
<?php
function buscar_nodo ( $nodo , $datos , $fichero , $case_sensitive ){
$encontrado = 0 ;
//Leemos el fichero
if(( $xml = leer_xml ( $fichero )) == - 1 ) return - 1 ;
//Comprobamos si es case sensitive
if(! $case_sensitive ) $case_sensitive = 0 ;
switch( $case_sensitive ){
case 0 :
//Recorremos los nodos
foreach( $xml -> $nodo as $tag )
foreach( $datos as $valor )
//Comparamos valor del nodo con el nuestro
if( strtolower ( $tag -> $valor [ 'tag' ]) == strtolower ( $valor [ 'dato' ])) $encontrado = 1 ;
break;
case 1 :
foreach( $xml -> $nodo as $tag )
foreach( $datos as $valor )
if( $tag -> $valor [ 'tag' ] == $valor [ 'dato' ]) $encontrado = 1 ;
break;
}
return $encontrado ;
}
?>
Modificar nodo: Modifica los valores de un nodo:
<?php
function modificar_nodo ( $tag , $dato , $viejo , $nuevo , $fichero ){
//Leemos el fichero
if(( $xml = leer_xml ( $fichero )) == - 1 ) return - 1 ;
//Recorremos los nodos
foreach( $xml -> $tag as $nodo ){
//Si encontramos nuestro nodo
if( $nodo -> $dato == $viejo ){
//Lo modificamos
$nodo -> $dato = $nuevo ;
$guardar = 1 ;
}
}
//Si hay cambios guardamos el fichero
if( $guardar ) $xml -> asXML ( $fichero );
return 0 ;
}
?>
Borrar nodo: Busca un valor en los nodos y si lo encuentra, borra el nodo entero
<?php
function borrar_nodo ( $tag , $dato , $valor , $fichero , $num_nodos ){
if(! $num_nodos ) $num_nodos = 1 ;
//Creamos un bucle con una iteración para cada nodo a borrar
for( $i = 0 ; $i < $num_nodos ; $i ++){
//Leemos el fichero
if(( $xml = leer_xml ( $fichero )) == - 1 ) return - 1 ;
//Recorreoms los nodos
foreach( $xml -> $tag as $nodo ){
//Si el valor del nodo->etiqueta = valor pasado
if( $nodo -> $dato == $valor ) {
//Borramos el nodo
$dom = dom_import_simplexml ( $nodo );
$dom -> parentNode -> removeChild ( $dom );
$guardar = 1 ;
}
}
//Si hay cambios guardamos el fichero
if( $guardar ) $xml -> asXML ( $fichero );
}
}
?>
Borrar nodo con case sensitive:
<?php
function borrar_nodo ( $tag , $dato , $valor , $fichero , $num_nodos , $case_sensitive ){
if(! $num_nodos ) $num_nodos = 1 ;
if(! $case_sensitive ) $case_sensitive = 0 ;
switch( $case_sensitive ){
case 0 :
//Creamos un bucle con una iteración para cada nodo a borrar
for( $i = 0 ; $i < $num_nodos ; $i ++){
//Leemos el fichero
if(( $xml = leer_xml ( $fichero )) == - 1 ) return - 1 ;
//Recorreoms los nodos
foreach( $xml -> $tag as $nodo ){
//Si el valor del nodo->etiqueta = valor pasado
if( strtolower ( $nodo -> $dato ) == strtolower ( $valor )) {
//Borramos el nodo
$dom = dom_import_simplexml ( $nodo );
$dom -> parentNode -> removeChild ( $dom );
$guardar = 1 ;
}
}
//Si hay cambios guardamos el fichero
if( $guardar ) $xml -> asXML ( $fichero );
}
break;
case 1 :
//Creamos un bucle con una iteración para cada nodo a borrar
for( $i = 0 ; $i < $num_nodos ; $i ++){
//Leemos el fichero
if(( $xml = leer_xml ( $fichero )) == - 1 ) return - 1 ;
//Recorreoms los nodos
foreach( $xml -> $tag as $nodo ){
//Si el valor del nodo->etiqueta = valor pasado
if( $nodo -> $dato == $valor ) {
//Borramos el nodo
$dom = dom_import_simplexml ( $nodo );
$dom -> parentNode -> removeChild ( $dom );
$guardar = 1 ;
}
}
//Si hay cambios guardamos el fichero
if( $guardar ) $xml -> asXML ( $fichero );
}
break;
}
}
?>
Manejo de las funciones:
leer_xml:le pasas la dirección de un fichero que contiene la estructura xml.
insertar_nodo:le pasas la etiqueta padre del nodo, una estructura con datos, el ficheor a leer, si puede haber nodos duplicados y un vector con la información de las etiquetas a mirar para ver si es duplicado.
La estructura de datos será:
$datos[0]['tag'] = 'etiqueta1';
$datos[0]['dato'] = $valor;
$datos[1]['tag'] = 'etiqueta2';
$datos[1]['dato'] = $valor2;
La estructura de valores duplicados es igual, es decir, para cada etiqueta a mirar creas $duplicados ['tag'] = 'etiqueta a mirar a la hora de ver si es duplicado', $duplicados ['dato'] = 'valor a comparar';
buscar_nodo:le pasas la etiqueta padre, la estructura de datos a buscar (idéntica a las estructuras de insertar_nodo), el fichero donde está el xml y si es case sensitive, es decir, si debe tener en cuenta o no las mayúsculas). Este último parámetro ha de ser 0 para que no tenga en cuenta si son mayúsculas o minúsculas y debe ser 1 si se quiere que diferencie mayúsculas de minúsculas. El valor es opcional. Si no se le pasa vale 0.
modificar_nodo:le pasas la etiqueta padre, la sub_etiqueta a cambiar(igual que en funciones anteriores), el valor viejo que debe buscar para cambiarlo, el valor nuevo que debe poner y el fichero a leer.
borrar_nodo:le pasas la etiqueta padre, la sub_etiqueta a mirar para ver si es el nodo a borrar, el dato que debe contener esta etiqueta, el fichero y por último el número máximo de nodos a borrar en caso de que exista más de uno que cumpla el criterio.
Se nota que están recien sacadas del horno ya que las primeras reciben el primer parámetro como $nodo y las últimas como $tag... funcionar funcionan bien, lo que puede que les falte son nombres más coherentes a las variables. Lo dicho, se aceptan correcciones.
Y ahora el ejemplo práctico:
Estructura xml:
<?xml version="1.0" encoding="iso-8859-1"?>
<usuarios>
<usuario>
<nombre>Neo</nombre>
<password>4028a0e356acc947fcd2bfbf00cef11e128d484a</password>
<grupo>1</grupo>
</usuario>
<usuario>
<nombre>Neo</nombre>
<password>d554901301fe8447a1dd696ae7047e589b84bc13</password>
<grupo>2</grupo>
</usuario>
<usuario>
<nombre>Neo2</nombre>
<password>7d653cf00d747a9fbab213b6c2b335cfe8199ff3</password>
<grupo>3</grupo>
</usuario>
<usuario>
<nombre>Neo3</nombre>
<password>0821b1111851959bfd9f4f9e5e4a60b9a3cdfe16</password>
<grupo>1</grupo>
</usuario>
</usuarios>
Para insetar un nuevo usuario, con nombre "Neo4" y cotraseña "test" (las del ejemplo están codificadas pero aquí lo dejaremos en texto plano) con el grupo "2" sería así:
Valores a insertar:
$usuario = "Neo4";
$pass = "test";
$grupo = "2";
Estructura con valores a insertar:
$datos[0]['tag'] = 'nombre';
$datos[0]['dato'] = $nombre;
$datos[1]['tag'] = 'password';
$datos[1]['dato'] = $pass;
$datos[2]['tag'] = 'grupo';
$datos[2]['dato'] = $grupo;
Estructura con datos para verificar datos duplicados:
$duplicados[0]['tag'] = 'nombre';
$duplicados[0]['dato'] = $nombre;
El cuarto valor es un "1" para indicar que no puede haber nodos duplicados.
insertar_nodo("usuario",$datos,"includes/usuarios.xml",1,$duplicados);
Vamos a buscar si existe "Neo4" en el archivo de usuarios, sin tener en cuenta mayúsculas de minúsculas:
Creamos la estructura que indica las etiquetas a mirar y sus valores:
$vec[0]['tag'] = "nombre";
$vec[0]['dato'] = "neo4";
$existe_nodo = buscar_nodo("usuario",$vec,"includes/usuarios.xml");
No le pasamos el parámetro final, así que por defecto coje un 0 y por tanto no tiene en cuenta las mayúsculas y minúsculas.
Ahora cambiamos "Neo4" por "Neo5":
modificar_nodo("usuario","nombre","Neo4","Neo5","includes/usuarios.xml");
Ahora borramos Neo5:
borrar_nodo("usuario","nombre","Neo5","includes/usuarios.xml",5);
Errores y correcciones:
- A las funciones modificar_nodo y borrar_nodo les falta el parámetro $case_sensitive para poder o no tener en cuenta las mayúsculas/minúsculas
- He añadido borra_nodo con case sensitive, pero no la he probado (creo que si que irá bien). La pega es que has de pasarle sí o sí el número de nodos a borrar si quieres usar case_sensitive.
- La función modificar nodo modifica todos los nodos que encuentre que coincidan con el valor dado. Es case sensitive (de momento).
Muy buena la ayuda, me gusta la maner...
Espero que no les parezca dificil, pu...
nose
He intentado usar wordpress para el b...