2010-09-10 9 views

Respuesta

10

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. 
+0

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

+0

@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

0

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.

3

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; 
2

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.

0

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. 
0

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.

2

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.

0

VerySimpleXML también pueden caber para tal requisito: manejo del archivo de configuración.

Tiene una pequeña huella sobre todo.

Cuestiones relacionadas