11 octubre 2007

Trabajando con documentos XML (II)

Anteriormente vimos que cada documento XML podía llevar asociado un documento DTD. Los documentos DTD (Document Type Definition) definen la estructura y la sintaxis de un documento XML. Su misión es mantener la consistencia entre los elementos del documento XML para que todos los documentos de la misma clase mantengan un mismo estilo.

Nuestro documento cli.dtd va a ser el siguiente:

Veamos que hace cada línea:

!ELEMENT Clientes (Cliente*)

Aquí establecemos que el documento XML se va a llamar Clientes y que cada elemento se llamará Cliente. El asterístico significa que va a tener cero o más elementos de tipo Cliente. Si quisieramos que el nodo Cliente apareciese una o más veces utilizaríamos el caracter +.

!ELEMENT Cliente (nombre, nif, saldopte?, diaspago?)

La segunda línea nos dice de que campos está compuesto el nodo Cliente: nombre, nif, saldopte y diaspago. Todos los campos que no lleven el signo de interrogación son obligatorios (en este caso nombre y nif).

!ELEMENT nombre (#PCDATA)
!ELEMENT nif (#PCDATA)
!ELEMENT saldopte (#PCDATA)
!ELEMENT diaspago (#PCDATA)

Por último se describe el tipo de dato que van a contener los nodos finales. El atributo #PCDATA significa que puede contener cualquier valor.

Con este archivo al lado de nuestros documentos XML podemos hacer doble clic sobre los mismos para que se vean en cualquier navegador.

NAVEGANDO POR LOS NODOS DEL DOCUMENTO XML

Una vez que el documento ha sido analizado sintácticamente por la implementación DOM, los datos representados estarán disponibles en la jerarquía de nodos. Cada nodo corresponde a un elemento etiqueta del documento. Por ejemplo, para el documento de clientes.xml que hemos visto anteriormente tendríamos la siguiente jerarquía: El nodo raiz es Clientes que a su vez tiene nodos hijos con el nombre Cliente. Cada uno de esos nodos hijos tienen a su vez otros nodos hijos tales como (nombre, nif, importepte y diaspago). Esos nodos hijos actuan como los nodos finales de un arból ya no tienen más nodos hijos.

Para acceder a cada nodo se utiliza la interfaz IXMLNode, comenzando por el nodo raiz a través de la propiedad DocumentElement del componente XMLDocument.

LEYENDO EL VALOR DE LOS NODOS

Vamos a ver un ejemplo de cómo leer el saldo pentiende (saldopte) del primer cliente y mostrarlo por pantalla:

var
Cliente: IXMLNode;
begin
XML.LoadFromFile( ExtractFilePath( Application.ExeName ) + 'clientes.xml' );
XML.Active := True;
Cliente := XML.DocumentElement.ChildNodes[0];
ShowMessage( Cliente.ChildNodes['saldopte'].Text );
end;

Suponemos que el documento clientes.xml está en el mismo directorio que nuestro programa. Como se puede apreciar en el código hemos abierto el documento XML, lo hemos activado y a continuación hemos recogido el nodo del primer cliente dentro de la variable Cliente que es de tipo IXMLNode. Después hemos accedido a su nodo hijo llamado saldopte para leer su valor.

MODIFICANDO EL VALOR DE LOS NODOS

Utilizando el mismo sistema podemos modificar el valor de cada nodo. En el siguiente ejemplo voy a modificar el nombre del segundo cliente (ROSA MARTINEZ GUILLEN) por el de MARIA PEREZ ROJO:

var
Cliente: IXMLNode;
begin
XML.LoadFromFile( ExtractFilePath( Application.ExeName ) + 'clientes.xml' );
XML.Active := True;
Cliente := XML.DocumentElement.ChildNodes[1];
Cliente.ChildNodes['nombre'].Text := 'MARIA PEREZ ROJO';
XML.SaveToFile( ExtractFilePath( Application.ExeName ) + 'clientes2.xml' );
end;

Una vez modificado el nombre grabo todo el documento XML en otro archivo llamado clientes2.xml (aunque podía haber utilizado el mismo).

AÑADIENDO Y BORRANDO NODOS

Mediante el método AddChild podemos crear nuevos nodos hijos dentro de un documento XML. Veamos como dar de alta un nuevo cliente y guardar el archivo como clientes3.xml:

var
Cliente, Nodo: IXMLNode;
begin
XML.LoadFromFile( ExtractFilePath( Application.ExeName ) + 'clientes.xml' );
XML.Active := True;
Cliente := XML.DocumentElement.AddChild( 'Cliente' );
Cliente.Attributes['id'] := '3';
Nodo := Cliente.AddChild( 'nombre' );
Nodo.Text := 'PABLO PALAZON ALCOLEA';
Nodo := Cliente.AddChild( 'nif' );
Nodo.Text := '79469163E';
Nodo := Cliente.AddChild( 'saldopte' );
Nodo.Text := '0.00';
Nodo := Cliente.AddChild( 'diaspago' );
Nodo.Text := '15';
XML.SaveToFile( ExtractFilePath( Application.ExeName ) + 'clientes3.xml' );
end;

En esta ocasión utilizamos dos nodos: Cliente para crear el nodo padre y Nodo para crear cada uno de los nodos hijos.

Por último podemos eliminar elementos utilizando el método Delete cuyo parámetro es el número de nodo hijo que deseamos eliminar (siendo cero el primer elemento). Para eliminar el primer cliente de la lista hacemos los siguiente:

begin
XML.LoadFromFile( ExtractFilePath( Application.ExeName ) + 'clientes.xml' );
XML.Active := True;
XML.DocumentElement.ChildNodes.Delete( 0 );
XML.SaveToFile( ExtractFilePath( Application.ExeName ) + 'clientes4.xml' );
end;

Este código coge la lista de los dos clientes iniciales, elimina el primero y guarda el documento como clientes4.xml. De esta manera podemos crear una pequeña base de datos utilizando documentos XML.

En el próximo artículo veremos como simplificar aún más el manejo de archivos XML utilizando el asistente XML Data Binding.

Pruebas realizadas en Delphi 7.

3 comentarios:

David González Acén dijo...

Realmente muy útil.

Gracias

Mcorp dijo...

puedo copiar nodos completos de un xml a otro xml? existira alguna forma?

Unknown dijo...

Muy agradecido por el aporte.

Publicidad