puede alguien me ayudará a aprender cómo utilizar XML. Como prueba, quiero usar XML en lugar de archivos INI para guardar la configuración de un programa.xml configuración de la muestra/de aplicaciones en XML
Gracias
puede alguien me ayudará a aprender cómo utilizar XML. Como prueba, quiero usar XML en lugar de archivos INI para guardar la configuración de un programa.xml configuración de la muestra/de aplicaciones en XML
Gracias
Rigo, puede usar la interfaz IXMLDocument
o el objeto TXMLDocument
para interactuar con un documento XML.
Puede comprobar estos enlaces para obtener más información acerca de XML y Delphi
Comprobar este código de ejemplo, para aprender lo básico acerca de la administración de xml usando la interfaz IXMLDocument
.
program Delphi_XmlSaveSettings;
{$APPTYPE CONSOLE}
uses
ActiveX,
SysUtils,
XmlDoc,
XmlIntf;
//this class mimic the basics functionalities of an TIniFile
//you can improve a lot the code adding exception handling and more methods for specifics tasks.
type
TXMLSettings = class
private
FFileName: string;
FXMLDoc: IXMLDocument; //Main XMLObject
public
constructor Create(const FileName: string); overload;
destructor Destroy; override;
function ReadString(const Section, Key, default: string): string;
procedure WriteString(const Section, Key, Value: string);
function ReadInteger(const Section, Key: string; default: Integer): Integer;
procedure WriteInteger(const Section, Key: string; Value: Integer);
function ReadBoolean(const Section, Key: string; default: Boolean): Boolean;
procedure WriteBoolean(const Section, Key: string; Value: Boolean);
function ReadDouble(const Section, Key: string; default: Double): Double;
procedure WriteDouble(const Section, Key: string; Value: Double);
function ReadDateTime(const Section, Key: string; default: TDatetime): TDateTime;
procedure WriteDatetime(const Section, Key: string; Value: TDatetime);
function ReadDate(const Section, Key: string; default: TDatetime): TDateTime;
procedure WriteDate(const Section, Key: string; Value: TDatetime);
procedure Save;
end;
constructor TXMLSettings.Create(const FileName: string);
begin
inherited Create;
FFileName := FileName;
FXMLDoc := NewXMLDocument; //Create aNew instance of a XML Document
FXMLDoc.Encoding:= 'UTF-8'; //Set the encoding
FXMLDoc.Options := [doNodeAutoIndent];//optional, is used to indent the Xml document
if FileExists(FFileName) then
FXMLDoc.LoadFromFile(FFileName)
else
FXMLDoc.AddChild('Root'); //Create the root Node
end;
destructor TXMLSettings.Destroy;
begin
Save;
inherited;
end;
function TXMLSettings.ReadBoolean(const Section, Key: string; default: Boolean): Boolean;
begin
Result := Boolean(ReadInteger(Section, Key, Integer(default)));
end;
function TXMLSettings.ReadDate(const Section, Key: string; default: TDatetime): TDateTime;
begin
Result := StrToDate(ReadString(Section, Key, DateToStr(default)));
end;
function TXMLSettings.ReadDateTime(const Section, Key: string; default: TDatetime): TDateTime;
begin
Result := StrToDateTime(ReadString(Section, Key, DateTimeToStr(default)));
end;
function TXMLSettings.ReadDouble(const Section, Key: string; default: Double): Double;
begin
Result := StrToFloat(ReadString(Section, Key, FloatToStr(default)));
end;
function TXMLSettings.ReadInteger(const Section, Key: string; default: Integer): Integer;
begin
Result := StrToInt(ReadString(Section, Key, IntToStr(default)));
end;
function TXMLSettings.ReadString(const Section, Key, default: string): string;
var
XMLNode: IXMLNode;
begin
XMLNode := FXMLDoc.DocumentElement.ChildNodes.FindNode(Section);
if Assigned(XMLNode) and XMLNode.HasAttribute(Key) then //Check if exist the Key
Result := XMLNode.Attributes[Key]
else
Result := default;
end;
procedure TXMLSettings.Save;
begin
FXMLDoc.SaveToFile(FFileName);
end;
procedure TXMLSettings.WriteBoolean(const Section, Key: string; Value: Boolean);
begin
WriteInteger(Section, Key, Integer(Value));
end;
procedure TXMLSettings.WriteDate(const Section, Key: string; Value: TDatetime);
begin
WriteString(Section, Key, DateToStr(Value));
end;
procedure TXMLSettings.WriteDatetime(const Section, Key: string; Value: TDatetime);
begin
WriteString(Section, Key, DateTimeToStr(Value));
end;
procedure TXMLSettings.WriteDouble(const Section, Key: string; Value: Double);
begin
WriteString(Section, Key, FloatToStr(Value));
end;
procedure TXMLSettings.WriteInteger(const Section, Key: string; Value: Integer);
begin
WriteString(Section, Key, IntToStr(Value));
end;
procedure TXMLSettings.WriteString(const Section, Key, Value: string);
var
XMLNode: IXMLNode;
begin
XMLNode := FXMLDoc.DocumentElement.ChildNodes.FindNode(Section);
if not Assigned(XMLNode) then
XMLNode := FXMLDoc.DocumentElement.AddChild(Section);
XMLNode.Attributes[Key] := Value;
end;
Procedure SaveSettings; //Store the settings
Var
AppSettings : TXMLSettings;
begin
AppSettings:=TXMLSettings.Create(ExtractFilePath(ParamStr(0))+'MySettings.xml');
try
AppSettings.WriteString('Server','Type','SQLServer');
AppSettings.WriteString('Server','User','root');
AppSettings.WriteInteger('Server','port',1433);
AppSettings.WriteString('Server','IP','192.168.1.1');
AppSettings.WriteString('Server','Database','Prod');
AppSettings.WriteBoolean('Server','WindowsAuth',False);
AppSettings.WriteDouble('Server','Latency',25.90892);
AppSettings.WriteDatetime('Server','LastAccess',Now);
AppSettings.WriteDate('Server','ActualDate',Now);
AppSettings.Save;
finally
AppSettings.Free;
end;
Writeln('Settings Saved');
end;
Procedure ShowSettings;//Read the settings
Var
AppSettings : TXMLSettings;
begin
AppSettings:=TXMLSettings.Create(ExtractFilePath(ParamStr(0))+'MySettings.xml');
try
Writeln(Format('Type %s',[AppSettings.ReadString('Server','Type','')]));
Writeln(Format('Port %d',[AppSettings.ReadInteger('Server','port',0)]));
Writeln(Format('IP %s',[AppSettings.ReadString('Server','IP','')]));
Writeln(Format('Database %s',[AppSettings.ReadString('Server','Database','')]));
Writeln(Format('WindowsAuth %s',[BoolToStr(AppSettings.ReadBoolean('Server','WindowsAuth',True),True)]));
Writeln(Format('Latency %g',[AppSettings.ReadDouble('Server','Latency',0)]));
Writeln(Format('LastAccess %s',[DateTimeToStr(AppSettings.ReadDateTime('Server','LastAccess',Now-1))]));
Writeln(Format('ActualDate %s',[DateToStr(AppSettings.ReadDate('Server','ActualDate',Now-1))]));
finally
AppSettings.Free;
end;
end;
begin
try
CoInitialize(nil); //only necesary in console applications
try
SaveSettings; //Save the sample settings
ShowSettings; //Read the stored settings
Readln;
finally
CoUninitialize; //only necesary in console applications
end;
except
on E:Exception do
Writeln(E.Classname, ': ', E.Message);
end;
end.
Dependiendo de qué edición de Delphi que está utilizando, que pueden o no tener el componente TXMLDocument disponible. Si no lo hace, tendrá que usar una biblioteca/componente XML de un tercero. Yo prefiero libxml2 mí mismo, y tiene una disposición vinculante para Pascal/Delphi.
Creo que RRUZ en su mayoría lo tiene todo.
También puede mirar en SimpleStorage porque fue hecha simplemente con tareas como esto en mente. Lo uso para la manipulación de todas las configuraciones de mi programa. Por ejemplo aquí es uno de esos ejemplos que uso (se puede ver que simplifica código porque no es necesario para comprobar si existen un nodo o un valor):
El XML:
<Settings>
<Service>
<Name>*********</Name>
<DisplayName>*********</DisplayName>
<Description>************</Description>
</Service>
<Http>
<ListenQueue>1000</ListenQueue>
<Port>8778</Port>
</Http>
<IPC>
<Name>*******</Name>
</IPC>
<Modules>
<Default>
<Protocol>ISAPI</Protocol>
<MaxProcNum>5</MaxProcNum>
<MemoryLimit>500</MemoryLimit>
</Default>
</Modules>
</Settings>
Y La código:
procedure THydraSettings.LoadSettings(const RootPath: string);
var
Settings: ISimpleStorage;
DefaulNode: IElement;
DefExtDir: string;
begin
DefExtDir := ExtractFilePath(ParamStr(0)) + DIR_EXTENSIONS;
Settings := StorageFromFile(RootPath + XML_SettingsFile);
FExtensionsDir := Settings.Get(cNode_Extensions).AsStringDef(DefExtDir);
FExtensionsDir := IncludeTrailingPathDelimiter(FExtensionsDir);
// IPC server based settings
FIPC.Name := Settings.Get(cNode_IPCName).AsStringDef('AI_Hydra');
// http server based settings
FHTTP.ServerPort := Settings.Get(cNode_HttpPort).AsIntegerDef(80);
FHTTP.ListenQueue := Settings.Get(cNode_ListenQueue).AsIntegerDef(100);
// get the defaults settings for modules
DefaulNode := Settings.Get([cNode_Modules, cNode_Default]);
FProtocol := DefaulNode.Get(cNode_Protocol).AsStringDef('ISAPI');
FMaxProcNum := DefaulNode.Get(cNode_MaxProcNum).AsIntegerDef(5);
FMemoryLimit := DefaulNode.Get(cNode_MemoryLimit).AsIntegerDef;
FTimeout := DefaulNode.Get(cNode_MemoryLimit).AsIntegerDef(30);
FUnload := DefaulNode.Get(cNode_Unload).AsBooleanDef;
end;
En las últimas versiones de Delphi, 2009+ creo, hay una unidad llamada XMLIniFile que contiene una envoltura alrededor xml TIniFile llama TXMLIniFile, y también TXMLMemIniFile.
Sin embargo en mi instalación de Delphi 2010 XMLIniFile.pas falta y sólo XMLIniFile.dcu está presente, todavía se puede utilizar, por supuesto, sin embargo. Además, parece no estar documentado, incluso en Delphi DocWiki.
De swissdelphicenter
http://www.swissdelphicenter.ch/torry/showcode.php?id=2269
{This code shows how to use TXMLDocument to save and restore configuration
settings in a XML document. The public methods works the same as a TIniFile.
There is not mutch comment in the code because it is self explaining
and small. Hope this benefit other persons. It is only tested in D7 pro.}
unit uCiaXml;
interface
uses
Forms, SysUtils, Windows, XmlIntf, XMLDoc;
type
TXMLConfig = class
private
FModified: Boolean;
FFileName: string;
FXMLDoc: TXMLDocument;
FBackup: Boolean;
function GetVersion: string;
public
constructor Create(const FileName: string); overload;
constructor Create; overload;
destructor Destroy; override;
procedure Save;
function ReadString(const Section, Key, default: string): string;
procedure WriteString(const Section, Key, Value: string);
function ReadInteger(const Section, Key: string; default: Integer): Integer;
procedure WriteInteger(const Section, Key: string; Value: Integer);
function ReadBoolean(const Section, Key: string; default: Boolean): Boolean;
procedure WriteBoolean(const Section, Key: string; Value: Boolean);
property Backup: Boolean read FBackup write FBackup;
property Version: string read GetVersion;
end;
implementation
{ TXMLConfig }
constructor TXMLConfig.Create(const FileName: string);
begin
inherited Create;
FBackup := True;
FFileName := FileName;
FXMLDoc := TXMLDocument.Create(Application);
FXMLDoc.Options := [doNodeAutoIndent];
if FileExists(FFileName) then
FXMLDoc.LoadFromFile(FFileName)
else
begin
FXMLDoc.Active := True;
FXMLDoc.AddChild('Configuration');
end;
end;
constructor TXMLConfig.Create;
begin
Create(ChangeFileExt(Application.Exename, '_cfg.xml'));
end;
destructor TXMLConfig.Destroy;
begin
Save;
FXMLDoc.Destroy;
inherited;
end;
function TXMLConfig.GetVersion: string;
begin
Result := '1.00';
end;
function TXMLConfig.ReadBoolean(const Section, Key: string; default: Boolean): Boolean;
begin
Result := Boolean(ReadInteger(Section, Key, Integer(default)));
end;
function TXMLConfig.ReadInteger(const Section, Key: string; default: Integer): Integer;
begin
Result := StrToInt(ReadString(Section, Key, IntToStr(default)));
end;
function TXMLConfig.ReadString(const Section, Key, default: string): string;
var
Node: IXMLNode;
begin
Node := FXMLDoc.DocumentElement.ChildNodes.FindNode(Section);
if Assigned(Node) and Node.HasAttribute(Key) then
Result := Node.Attributes[Key]
else
Result := default;
end;
procedure TXMLConfig.Save;
begin
if not FModified then
Exit;
if FBackup then
CopyFile(PChar(FFileName), PChar(FFileName + '.bak'), False);
FXMLDoc.SaveToFile(FFileName);
FModified := False;
end;
procedure TXMLConfig.WriteBoolean(const Section, Key: string; Value: Boolean);
begin
WriteInteger(Section, Key, Integer(Value));
end;
procedure TXMLConfig.WriteInteger(const Section, Key: string; Value: Integer);
begin
WriteString(Section, Key, IntToStr(Value));
end;
procedure TXMLConfig.WriteString(const Section, Key, Value: string);
var
Node: IXMLNode;
begin
if ReadString(Section, Key, '') = Value then
Exit;
Node := FXMLDoc.DocumentElement.ChildNodes.FindNode(Section);
if not Assigned(Node) then
Node := FXMLDoc.DocumentElement.AddChild(Section);
Node.Attributes[Key] := Value;
FModified := True;
end;
end.
Para guardar la configuración en un archivo XML, puede utilizar la biblioteca OmniXML.Es bastante simple de usar con derivados TPersistent:
permite decir:
type
TConfig = class(TPersistent)
private
FSomeOption: string;
published
SomeOption: string read FSomeOption write FSomeOption;
end;
entonces, con una sola línea de código se puede almacenar en un archivo xml:
begin
TOmniXMLWriter.SaveToFile(Config, ConfigFileName, pfNodes, ofIndent)
end;
donde Config es una instancia de TConfig.
Usted puede leer un poco más sobre esto en my blog (traducido del español con Google)
Saludos.
La biblioteca de código abierto Jedi VCL contiene una claseTJvAppXMLFileStorage (en la unidad JvAppXMLStorage) que almacena la configuración en un archivo XML.
TJvAppXMLFileStorage es un almacenamiento de datos back-end que almacena los datos en un archivo XML .
Como descendiente de TJvCustomAppXMLStorage que proporciona la interfaz estándar para almacenar datos (tales como ajustes de posiciones, de forma y tamaños, etc) en un formato de archivo XML. Estos datos se almacenarán en un archivo real , representado en la memoria a través de el uso de un objeto TJvSimpleXML.
VerySimpleXML también pueden caber para tal requisito: manejo del archivo de configuración.
Tiene una pequeña huella sobre todo.
Es un buen ejemplo, pero solo una nota. Usted imita el archivo INI aquí. Creo que el poder de XML sobre el INI radica en la flexibilidad de XML y la infinita profundidad que puede tener. Buen ejemplo de lo contrario :) – Runner
@Runner, le doy a esta muestra solo un enfoque simple para usar el XML para guardar la configuración de una aplicación, obviamente el OP puede implementar una solución más flexible y compleja cuando conoce el XML en profundidad. – RRUZ