2010-09-10 28 views

回答

10

Rigo,您可以使用IXMLDocument接口或TXMLDocument對象與XML文檔進行交互。

您可以檢查這些鏈接,瞭解有關XML和德爾福的更多信息

入住此示例代碼,學習的基礎知識關於使用IXMLDocument接口的xml管理。

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

這是一個很好的例子,但只是一個說明。你在這裏模擬INI文件。我認爲XML在INI上的強大之處在於XML靈活性和您可以擁有的無限深度。好的例子:) – Runner 2010-09-11 05:07:18

+0

@Runner,我給這個例子就像使用XML保存應用程序設置的簡單方法一樣,顯然,OP可以在深入瞭解XML時實現更靈活和更復雜的解決方案。 – RRUZ 2010-09-11 06:03:06

0

根據德爾福的版本使用的是,您可能會或可能不會有TXMLDocument的組件可用。如果你不這樣做,那麼你將不得不使用第三方XML庫/組件。我自己更喜歡libxml2,它有一個可用於Pascal/Delphi的綁定。

3

我認爲RRUZ主要都是這樣。

您也可以查看SimpleStorage,因爲它只是考慮到這樣的任務而設計的。我用它來處理我所有的程序設置。例如,下面是這樣的例子我用一個(你可以看到它簡化了代碼,因爲你並不需要檢查,如果一個節點或值存在):

的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> 

和代碼:

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

在最近版本的Delphi,2009+,我相信,有一個叫XMLIniFile單元包含一個xml來包裹TIniFile稱爲TXMLIniFile,也TXMLMemIniFile。

但是,在我安裝的Delphi 2010中,XMLIniFile.pas丟失,只有XMLIniFile.dcu存在,當然你仍然可以使用它。此外,它似乎沒有記錄,即使在Delphi DocWiki上也是如此。

0

從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

存儲配置在一個XML文件中,你可以使用OmniXML庫。這是很簡單的用TPersistent衍生物的使用方法:

讓說:

type 
    TConfig = class(TPersistent) 
    private 
    FSomeOption: string; 
    published 
    SomeOption: string read FSomeOption write FSomeOption; 
    end; 

然後,用一個單一的代碼行,你可以將它存儲到一個XML文件:

begin 
    TOmniXMLWriter.SaveToFile(Config, ConfigFileName, pfNodes, ofIndent) 
end; 

,其中配置是一個TConfig的實例。

你可以讀到更多一點關於這my blog(譯自西班牙語與谷歌)

最好的問候。

2

開源Jedi VCL庫包含TJvAppXMLFileStorage類(在單元JvAppXMLStorage),其存儲在XML文件中的設置。

TJvAppXMLFileStorage是數據存儲 後端存儲在XML文件 數據。

作爲 TJvCustomAppXMLStorage的後代,它提供了 標準接口,用於以XML文件格式存儲數據 (如設置,表單位置 和大小等)。 這個數據將被存儲在一個實際的 文件中,在內存中通過 表示使用TJvSimpleXML對象。

0

VerySimpleXML也可能適合這樣的要求:處理配置文件。

它的佔地面積很小。