Implementación de persistencia de objetos en delphi mediante XML

Delphi no dispone de muchos sistemas para no decir ninguno que implemente la persistencia de Objetos como Java por ejemplo. Y como dice el pensamiento pragmático: no intentes diseccionar una rana, constrúyete tú una de nueva!. Pues allá vamos!.

Lo que he hecho, es crear las clases, y estas implementan unos métodos WriteToXML y ReadFromXML que guardan su contenido en un fichero XML. Por lo tanto cada instancia de clase, guarda todo su contenido en el fichero que se le pasa, y luego también puede recuperar todo su contenido a través de este.

Aquí os dejo un ejemplo bastante completo de mi última aplicación ThundaxSaveSeries, que permite guardar listas de series (Lost, Anatomia de Grey, 24h, Big bang, etc.) y queráis tener un pequeño registro donde indicar la temporada del capítulo, si lo habéis descargado, si lo habéis visto, etc. A mi me va bastante bien, ya que es mas portable que un excel.


En este ejemplo podéis ver como hago las llamadas a IXMLDocument, y accedo a sus nodos mediante IXMLNode.

unit Lib_Series;

interface

uses
Contnrs, SysUtils, XMLDoc, XMLIntf;

type
TEstado = (Vista, Descargada, Pendiente);

TCapitulo = class(TObject)
numero: integer;
Temporada: integer;
estado: TEstado;
constructor Create(temporada: integer; numero: integer; estado: TEstado);
function WriteToXML(XMLDoc: IXMLDocument; iXMLRootNode: IXMLNode; sNode: string): IXMLNode;
function ReadFromXML(XMLDoc: IXMLDocument; iXMLRootNode: IXMLNode): IXMLNode;
end;

TSerie = class(TObject)
Nombre: string;
NumCapitulos: integer;
CapituloInicial: integer;
temporada: integer;
TTemporada: TObjectList;
completa: boolean;
constructor Create(Nombre: string; Temporada: integer; NumCapitulos: integer; tieneCapituloZero: boolean);
function WriteToXML(XMLDoc: IXMLDocument; iXMLRootNode: IXMLNode; sNode: string): IXMLNode;
function ReadFromXML(XMLDoc: IXMLDocument; iXMLRootNode: IXMLNode; sNode: string): IXMLNode;
end;

TListaSeries = class(TObject)
ListaSeries: TObjectList;
constructor Create();
destructor Destroy(); override;
procedure WriteToXML(sArchivo: string);
procedure ReadFromXML(sArchivo: string);
end;

implementation

{ TListaSeries }

procedure TListaSeries.ReadFromXML(sArchivo: string);
var
Document: IXMLDocument;
iXMLRootNode, iXMLRootNode2: IXMLNode;
objSerie: TSerie;
begin
Document := TXMLDocument.Create(nil);
try
Document.LoadFromFile(sArchivo);
iXMLRootNode := Document.ChildNodes.First;
iXMLRootNode2 := iXMLRootNode.ChildNodes.first;
while iXMLRootNode2 <> nil do
begin
if iXMLRootNode2.NodeName = 'Serie' then
begin
objSerie := TSerie.CreateEmpty();
objSerie.ReadFromXML(Document, iXMLRootNode2, 'Serie');
Self.ListaSeries.Add(objSerie);
end;
iXMLRootNode2 := iXMLRootNode2.NextSibling;
end;
finally
Document := nil;
end;
end;

procedure TListaSeries.WriteToXML(sArchivo: string);
var
XMLDoc: TXMLDocument;
iNode, NodeSeccio: IXMLNode;
i: integer;
objSerie: TSerie;
begin
XMLDoc := TXMLDocument.Create(nil);
XMLDoc.Active := True;
iNode := XMLDoc.AddChild('TListaSeries');
for i := 0 to ListaSeries.count - 1 do
begin
NodeSeccio := iNode.AddChild('Serie');
objSerie := TSerie(ListaSeries[i]);
if objSerie <> nil then
objSerie.WriteToXML(XMLDoc, NodeSeccio, 'Serie');
end;
XMLDoc.SaveToFile(sArchivo);
end;

function TCapitulo.WriteToXML(XMLDoc: IXMLDocument; iXMLRootNode: IXMLNode; sNode: string): IXMLNode;
begin
iXMLRootNode.attributes['numero'] := IntToStr(Self.numero);
iXMLRootNode.attributes['Temporada'] := IntToStr(Self.Temporada);
iXMLRootNode.attributes['estado'] := TEstadoToStr(Self.estado);
end;

function TCapitulo.ReadFromXML(XMLDoc: IXMLDocument; iXMLRootNode: IXMLNode): IXMLNode;
begin
Self.numero := StrToInt(iXMLRootNode.attributes['numero']);
Self.Temporada := StrToInt(iXMLRootNode.attributes['Temporada']);
Self.estado := StrToTEstado(iXMLRootNode.attributes['estado']);
end;

function TSerie.WriteToXML(XMLDoc: IXMLDocument; iXMLRootNode: IXMLNode; sNode: string): IXMLNode;
var
iNodoObjeto: IXMLNode;
i: integer;
begin
iXMLRootNode.attributes['Nombre'] := Self.Nombre;
iXMLRootNode.attributes['NumCapitulos'] := IntToStr(Self.NumCapitulos);
iXMLRootNode.attributes['CapituloInicial'] := IntToStr(Self.CapituloInicial);
iXMLRootNode.attributes['temporada'] := IntToStr(Self.temporada);
iXMLRootNode.attributes['completa'] := BoolToStr(Self.completa);
for i := 0 to Self.TTemporada.Count - 1 do
begin
iNodoObjeto := iXMLRootNode.AddChild('Capitulos');
TCapitulo(Self.TTemporada.Items[i]).GuardarEnXML(XMLDoc, iNodoObjeto, 'Capitulos');
end;
end;

function TSerie.ReadFromXML(XMLDoc: IXMLDocument; iXMLRootNode: IXMLNode; sNode: string): IXMLNode;
var
iNodoObjeto, iNodoAtributo: IXMLNode;
objCapitulo: TCapitulo;
begin
iNodoObjeto := iXMLRootNode;
if iNodoObjeto.nodeName = sNode then
begin
Self.Nombre := iNodoObjeto.attributes['Nombre'];
Self.NumCapitulos := StrToInt(iNodoObjeto.attributes['NumCapitulos']);
Self.CapituloInicial := StrToInt(iNodoObjeto.attributes['CapituloInicial']);
Self.temporada := StrToInt(iNodoObjeto.attributes['temporada']);
Self.completa := StrToBool(iNodoObjeto.attributes['completa']);
iNodoAtributo := iNodoObjeto.ChildNodes.first;
while iNodoAtributo <> nil do
begin
objCapitulo := TCapitulo.CreateEmpty();
objCapitulo.ReadFromXMLDoc(XMLDoc, iNodoAtributo);
self.TTemporada.Add(objCapitulo);
iNodoAtributo := iNodoAtributo.nextSibling;
end;
end;
end;

end.








La persistencia de los objetos mediante su XML:


  • Enlaces de interés:

Podemos encontrar proyectos Open Source, que intentar hacer la persistencia de objetos para delphi, uno de estos es "Delphi Persistent Object" y lo podemos encontrar en SourceForge. Aquí os dejo el enlace directo:
http://sourceforge.net/projects/depo/

Comments

Popular Posts