tl; dr: Используйте мастер XML Data Binding для создания интерфейсов для обработки вашего конкретного XML-файла, ét voila.
Самый простой способ реализовать это - начать с файла XML.Например, создайте его следующим образом:
<?xml version="1.0"?>
<masteritems>
<masteritem>
<name>Caption1</name>
<value>123456</value>
<childitems>
<childitem>
<name>Caption1.1</name>
<value>23452</value>
</childitem>
<childitem>
<name>Caption1.2</name>
<value>65465</value>
</childitem>
</childitems>
</masteritem>
<masteritem>
...
</masteritem>
</masteritems>
Затем создайте интерфейсный модуль для этого типа XML-файла, используя Мастер привязки данных XML , см. Файл>Создать> Другое> Создать> Привязка данных XML .Настройте по своему усмотрению, но просто пройдя каждую страницу мастера нажатием OK, по умолчанию все работает отлично.(Обратите внимание, что настройки по умолчанию для других версий Delphi могут отличаться от моих.) Хотя мне лично нравится избавляться от суффикса «Тип» для каждого типа интерфейса.(Как и для имен типов классов, но это не вариант в мастере, так что вы можете сделать это вручную.)
А теперь, чтобы загрузить и обработать этот XML-файл:
uses
Classes, Controls, Forms, StdCtrls,
Test, xmldom, XMLIntf, msxmldom, XMLDoc;
type
TForm2 = class(TForm)
ListBox1: TListBox;
ListBox2: TListBox;
XMLDocument1: TXMLDocument; { See tab 'Internet' on component palette }
SaveButton: TButton;
procedure FormCreate(Sender: TObject);
procedure ListBox1Click(Sender: TObject);
procedure SaveButtonClick(Sender: TObject);
private
function CurrentMasterItem: IXMLMasterItem;
end;
...
function TForm2.CurrentMasterItem: IXMLMasterItem;
var
MasterItems: IXMLMasterItems;
I: Integer;
begin
MasterItems := GetMasterItems(XMLDocument1);
for I := 0 to MasterItems.Count - 1 do
begin
Result := MasterItems.Masteritem[I];
if Result.Name = ListBox1.Items[ListBox1.ItemIndex] then
Break;
end;
end;
procedure TForm2.FormCreate(Sender: TObject);
var
MasterItems: IXMLMasterItems;
I: Integer;
begin
XMLDocument1.FileName := 'Test.xml';
XMLDocument1.NodeIndentStr := '<tab>';
MasterItems := GetMasterItems(XMLDocument1);
for I := 0 to MasterItems.Count - 1 do
ListBox1.Items.Add(MasterItems[I].Name);
XMLDocument1.Active := False;
end;
procedure TForm2.ListBox1Click(Sender: TObject);
var
ChildItems: IXMLChildItems;
I: Integer;
begin
if ListBox1.ItemIndex > -1 then
begin
ChildItems := CurrentMasterItem.Childitems;
ListBox2.Clear;
for I := 0 to ChildItems.Count - 1 do
ListBox2.Items.AddObject(ChildItems[I].Name,
TObject(ChildItems[I].Value));
XMLDocument1.Active := False;
end;
end;
procedure TForm2.SaveButtonClick(Sender: TObject);
var
ChildItems: IXMLChildItems;
ChildItem: IXMLChildItem;
I: Integer;
begin
if ListBox1.ItemIndex > -1 then
begin
ListBox2.Items.AddObject('New item', TObject(543223));
ChildItems := CurrentMasterItem.Childitems;
ChildItems.Clear;
for I := 0 to ListBox2.Count - 1 do
begin
ChildItem := ChildItems.Add;
ChildItem.Name := ListBox2.Items[I];
ChildItem.Value := Integer(ListBox2.Items.Objects[I]);
end;
XMLDocument1.SaveToFile(XMLDocument1.FileName);
XMLDocument1.Active := False;
end;
end;
Обновление: Это единица, созданная мастером здесь:
{*********************************************************}
{ }
{ XML Data Binding }
{ }
{ Generated on: 10-11-2011 23:25:30 }
{ Generated from: H:\Delphi\Test\XMLTest\Test.xml }
{ Settings stored in: H:\Delphi\Test\XMLTest\Test.xdb }
{ }
{*********************************************************}
unit Test;
interface
uses xmldom, XMLDoc, XMLIntf;
type
{ Forward Decls }
IXMLMasterItems = interface;
IXMLMasterItem = interface;
IXMLChildItems = interface;
IXMLChildItem = interface;
{ IXMLMasterItems }
IXMLMasterItems = interface(IXMLNodeCollection)
['{ACA35986-053A-40AE-92E8-2044BC5DADC6}']
{ Property Accessors }
function Get_Masteritem(Index: Integer): IXMLMasterItem;
{ Methods & Properties }
function Add: IXMLMasterItem;
function Insert(const Index: Integer): IXMLMasterItem;
property Masteritem[Index: Integer]: IXMLMasterItem
read Get_Masteritem; default;
end;
{ IXMLMasterItem }
IXMLMasterItem = interface(IXMLNode)
['{E6481675-AE5B-4166-A977-CA29EC97B78D}']
{ Property Accessors }
function Get_Name: WideString;
function Get_Value: Integer;
function Get_Childitems: IXMLChildItems;
procedure Set_Name(Value: WideString);
procedure Set_Value(Value: Integer);
{ Methods & Properties }
property Name: WideString read Get_Name write Set_Name;
property Value: Integer read Get_Value write Set_Value;
property Childitems: IXMLChildItems read Get_Childitems;
end;
{ IXMLChildItems }
IXMLChildItems = interface(IXMLNodeCollection)
['{CD16D91C-30E5-45A1-AAA1-1C518C84EA5B}']
{ Property Accessors }
function Get_Childitem(Index: Integer): IXMLChildItem;
{ Methods & Properties }
function Add: IXMLChildItem;
function Insert(const Index: Integer): IXMLChildItem;
property Childitem[Index: Integer]: IXMLChildItem
read Get_Childitem; default;
end;
{ IXMLChildItem }
IXMLChildItem = interface(IXMLNode)
['{F7399037-A33F-4E43-ADF9-000EAD71B418}']
{ Property Accessors }
function Get_Name: WideString;
function Get_Value: Integer;
procedure Set_Name(Value: WideString);
procedure Set_Value(Value: Integer);
{ Methods & Properties }
property Name: WideString read Get_Name write Set_Name;
property Value: Integer read Get_Value write Set_Value;
end;
{ Forward Decls }
TXMLMasteritemsType = class;
TXMLMasteritemType = class;
TXMLChilditemsType = class;
TXMLChilditemType = class;
{ TXMLMasteritemsType }
TXMLMasteritemsType = class(TXMLNodeCollection, IXMLMasterItems)
protected
{ IXMLMasterItems }
function Get_Masteritem(Index: Integer): IXMLMasterItem;
function Add: IXMLMasterItem;
function Insert(const Index: Integer): IXMLMasterItem;
public
procedure AfterConstruction; override;
end;
{ TXMLMasteritemType }
TXMLMasteritemType = class(TXMLNode, IXMLMasterItem)
protected
{ IXMLMasterItem }
function Get_Name: WideString;
function Get_Value: Integer;
function Get_Childitems: IXMLChildItems;
procedure Set_Name(Value: WideString);
procedure Set_Value(Value: Integer);
public
procedure AfterConstruction; override;
end;
{ TXMLChilditemsType }
TXMLChilditemsType = class(TXMLNodeCollection, IXMLChildItems)
protected
{ IXMLChildItems }
function Get_Childitem(Index: Integer): IXMLChildItem;
function Add: IXMLChildItem;
function Insert(const Index: Integer): IXMLChildItem;
public
procedure AfterConstruction; override;
end;
{ TXMLChilditemType }
TXMLChilditemType = class(TXMLNode, IXMLChildItem)
protected
{ IXMLChildItem }
function Get_Name: WideString;
function Get_Value: Integer;
procedure Set_Name(Value: WideString);
procedure Set_Value(Value: Integer);
end;
{ Global Functions }
function Getmasteritems(Doc: IXMLDocument): IXMLMasterItems;
function Loadmasteritems(const FileName: WideString): IXMLMasterItems;
function Newmasteritems: IXMLMasterItems;
const
TargetNamespace = '';
implementation
{ Global Functions }
function Getmasteritems(Doc: IXMLDocument): IXMLMasterItems;
begin
Result := Doc.GetDocBinding('masteritems',
TXMLMasteritemsType, TargetNamespace) as IXMLMasterItems;
end;
function Loadmasteritems(const FileName: WideString): IXMLMasterItems;
begin
Result := LoadXMLDocument(FileName).GetDocBinding('masteritems',
TXMLMasteritemsType, TargetNamespace) as IXMLMasterItems;
end;
function Newmasteritems: IXMLMasterItems;
begin
Result := NewXMLDocument.GetDocBinding('masteritems',
TXMLMasteritemsType, TargetNamespace) as IXMLMasterItems;
end;
{ TXMLMasteritemsType }
procedure TXMLMasteritemsType.AfterConstruction;
begin
RegisterChildNode('masteritem', TXMLMasteritemType);
ItemTag := 'masteritem';
ItemInterface := IXMLMasterItem;
inherited;
end;
function TXMLMasteritemsType.Get_Masteritem(Index: Integer): IXMLMasterItem;
begin
Result := List[Index] as IXMLMasterItem;
end;
function TXMLMasteritemsType.Add: IXMLMasterItem;
begin
Result := AddItem(-1) as IXMLMasterItem;
end;
function TXMLMasteritemsType.Insert(const Index: Integer): IXMLMasterItem;
begin
Result := AddItem(Index) as IXMLMasterItem;
end;
{ TXMLMasteritemType }
procedure TXMLMasteritemType.AfterConstruction;
begin
RegisterChildNode('childitems', TXMLChilditemsType);
inherited;
end;
function TXMLMasteritemType.Get_Name: WideString;
begin
Result := ChildNodes['name'].Text;
end;
procedure TXMLMasteritemType.Set_Name(Value: WideString);
begin
ChildNodes['name'].NodeValue := Value;
end;
function TXMLMasteritemType.Get_Value: Integer;
begin
Result := ChildNodes['value'].NodeValue;
end;
procedure TXMLMasteritemType.Set_Value(Value: Integer);
begin
ChildNodes['value'].NodeValue := Value;
end;
function TXMLMasteritemType.Get_Childitems: IXMLChildItems;
begin
Result := ChildNodes['childitems'] as IXMLChildItems;
end;
{ TXMLChilditemsType }
procedure TXMLChilditemsType.AfterConstruction;
begin
RegisterChildNode('childitem', TXMLChilditemType);
ItemTag := 'childitem';
ItemInterface := IXMLChildItem;
inherited;
end;
function TXMLChilditemsType.Get_Childitem(Index: Integer): IXMLChildItem;
begin
Result := List[Index] as IXMLChildItem;
end;
function TXMLChilditemsType.Add: IXMLChildItem;
begin
Result := AddItem(-1) as IXMLChildItem;
end;
function TXMLChilditemsType.Insert(const Index: Integer): IXMLChildItem;
begin
Result := AddItem(Index) as IXMLChildItem;
end;
{ TXMLChilditemType }
function TXMLChilditemType.Get_Name: WideString;
begin
Result := ChildNodes['name'].Text;
end;
procedure TXMLChilditemType.Set_Name(Value: WideString);
begin
ChildNodes['name'].NodeValue := Value;
end;
function TXMLChilditemType.Get_Value: Integer;
begin
Result := ChildNodes['value'].NodeValue;
end;
procedure TXMLChilditemType.Set_Value(Value: Integer);
begin
ChildNodes['value'].NodeValue := Value;
end;
end.