Czy ktoś może mi pomóc, aby nauczyć się korzystać z XML. Jako test chcę użyć XML zamiast plików INI do zapisania ustawień programu.Ustawienia przykładowej/aplikacji xml w xml
Dzięki
Czy ktoś może mi pomóc, aby nauczyć się korzystać z XML. Jako test chcę użyć XML zamiast plików INI do zapisania ustawień programu.Ustawienia przykładowej/aplikacji xml w xml
Dzięki
Rigo, można użyć interfejsu IXMLDocument
lub obiektu TXMLDocument
do interakcji z dokumentem XML.
Można sprawdzić te linki, aby uzyskać więcej informacji na temat XML i Delphi
Odjazd ten przykładowy kod, aby nauczyć się podstaw o zarządzaniu xml przy użyciu interfejsu 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.
zależności od edycja Delphi używasz, może lub nie może mieć składnik TXMLDocument dostępny. Jeśli tego nie zrobisz, będziesz musiał użyć biblioteki/składnika XML innej firmy. Ja sam wolę libxml2 i ma on powiązanie dostępne dla Pascal/Delphi.
Myślę, że RRUZ w większości ma wszystko.
Możesz również spojrzeć na SimpleStorage, ponieważ została stworzona właśnie z myślą o tym. Używam go do wszystkich manipulacji ustawieniami mojego programu. Na przykład tutaj jest jednym z takich przykładów używam (można go zobaczyć upraszcza kod bo nie trzeba by sprawdzić, czy węzeł lub wartość istnieją):
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>
And The Kod:
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;
W ostatnich wersjach Delphi, 2009+ wierzę, że jest to jednostka o nazwie XMLIniFile który zawiera opakowanie xml wokół TIniFile nazywa TXMLIniFile, a także TXMLMemIniFile.
Jednak w mojej instalacji Delphi 2010 XMLIniFile.pas brakuje i tylko XMLIniFile.dcu jest obecny, nadal można go używać oczywiście. Ponadto wydaje się być nieudokumentowanym, nawet w Docwiki Delphi.
Od 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.
Aby zapisać konfigurację w pliku XML, można użyć biblioteki OmniXML.Jest to dość proste w użyciu pochodnych TPersistent:
powiedzmy:
type
TConfig = class(TPersistent)
private
FSomeOption: string;
published
SomeOption: string read FSomeOption write FSomeOption;
end;
następnie, z jednej linii kodu można zapisać go do pliku XML:
begin
TOmniXMLWriter.SaveToFile(Config, ConfigFileName, pfNodes, ofIndent)
end;
gdzie config instancja TConfig.
można przeczytać nieco więcej na ten temat w my blog (przetłumaczony z języka hiszpańskiego z Google)
pozdrawiam.
open source Jedi VCL biblioteka zawiera TJvAppXMLFileStorage klasę (w jednostkach JvAppXMLStorage), która przechowuje ustawienia w pliku XML.
TJvAppXMLFileStorage jest przechowywanie danych backend, który przechowuje dane w pliku XML .
Jako potomek TJvCustomAppXMLStorage Zapewnia standardowy interfejs do przechowywania danych (takie jak ustawienia, pozycjach formularza i rozmiarach, etc) w formacie XML . Dane te będą przechowywane w rzeczywistym pliku , reprezentowanym w pamięci przez użycie obiektu TJvSimpleXML.
VerySimpleXML może również spełniać takie wymagania: obsługa pliku konfiguracyjnego.
Ma niewielki rozmiar przede wszystkim.
Jest to dobry przykład, ale tylko notatkę. Naśladujesz plik INI tutaj. Myślę, że moc XML nad INI polega na elastyczności XML i nieskończonej głębi, jaką możesz mieć. Dobry przykład inaczej :) – Runner
@Runner, podaję tę próbkę w prosty sposób, aby użyć XML do zapisania ustawień aplikacji, oczywiście OP może zaimplementować bardziej elastyczne i złożone rozwiązanie, gdy zna XML w głębi. – RRUZ