Reputation: 2416
Hy! I want to add IXMLNodes to an XML document. My main procedure is btnXmlSaveToFileClick which Saves XML structure to a file. My problem is I cannot add IXMLNode as a child. Sorry for my English.
Any help or advice would be greatly appreciated.
Here is my example:
*
unit Unit3;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
XMLDoc, XMLIntf, Vcl.StdCtrls;
type
IXMLDataSample1 = interface(IXMLNode)
['{D7B7E084-1BF8-4185-85D1-1C83B74EA651}']
function GetXmlDAtaSample1: WideString;
procedure SetXmlDAtaSample1(const Value: WideString);
property XmlDataSample1: WideString read GetXmlDataSample1 write SetXmlDataSample1;
end;
IXMLDataSample2 = interface(IXMLNode)
['{6D7CE38B-3F57-4F18-A337-8405E72637E6}']
function GetXmlDataSample2: WideString;
procedure SetXmlDataSample2(const Value: WideString);
property XmlDataSample2: WideString read GetXmlDataSample2 write SetXmlDataSample2;
end;
TXMLHandler<IXMLType: IXMLNode> = class
private
class function ConvertXMLNodeToXMLType(aNode: IXMLNode): IXMLType;
protected
class function GetXMLClass: TClass; virtual; abstract;
class function GetXMLRootElementName: WideString; virtual; abstract;
class function GetXMLIfType: TGUID; virtual; abstract;
class procedure SaveXMLToFile(aXML: IXMLType; const aFileName: string);
class function NewXML: IXMLType; virtual;
end;
TDataSampleXMLHandler1 = class(TXMLHandler<IXMLDataSample1>)
public
class function GetXMLClass: TClass; override;
class function GetXMLRootElementName: WideString; override;
class function GetXMLIfType: TGUID; override;
end;
TDataSampleXMLHandler12 = class(TXMLHandler<IXMLDataSample2>)
protected
class function GetXMLClass: TClass; override;
class function GetXMLRootElementName: WideString; override;
class function GetXMLIfType: TGUID; override;
end;
TForm3 = class(TForm)
btnXmlSaveToFile: TButton;
procedure btnXmlSaveToFileClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form3: TForm3;
implementation
{$R *.dfm}
type
TXMLSampleDataObj1 = class(TXMLNode, IXMLDataSample1)
private
function GetXmlDataSample1: WideString;
procedure SetXmlDataSample1(const Value: WideString);
end;
TXMLSampleDataObj2 = class(TXMLNode, IXMLDataSample2)
private
function GetXMlDataSample2: WideString;
procedure SetXmlDAtaSample2(const Value: WideString);
end;
procedure TForm3.btnXmlSaveToFileClick(Sender: TObject);
//Works well
vXML1 := TDataSampleXMLHandler1.NewXML;
vXML1.XmlDataSample1 := 'test data';
TDataSampleXMLHandler1.SaveXMLToFile(vXml1, 'C:\Teszt\XmlSample.XML');
//My problem here, cannot add IXMLNode to XMLDocument
vXMLDoc := NewXMLDocument;
vXMLDoc.ChildNodes.Add(vXML1);
//And add vXML2 and more...
vXMLDoc.SaveToFile('C:\Teszt\XmlDocSaveSAmple.XML');
end;
{ TXMLHandler<IXMLType> }
class function TXMLHandler<IXMLType>.ConvertXMLNodeToXMLType(
aNode: IXMLNode): IXMLType;
begin
Result := default(IXMLType);
try
Supports(aNode, GetXMLIfType, result);
finally
aNode := nil;
end;
end;
class function TXMLHandler<IXMLType>.NewXML: IXMLType;
begin
Result :=
ConvertXMLNodeToXMLType(NewXMLDocument.GetDocBinding(GetXMLRootElementName, GetXMLClass, ''));
end;
class procedure TXMLHandler<IXMLType>.SaveXMLToFile(aXML: IXMLType;
const aFileName: string);
begin
aXML.OwnerDocument.SaveToFile(aFileName);
end;
{ TDataSampleXMLHandler12 }
class function TDataSampleXMLHandler12.GetXMLClass: TClass;
begin
Result := TXMLSampleDataObj2;
end;
class function TDataSampleXMLHandler12.GetXMLIfType: TGUID;
begin
Result := IXMLDataSample2;
end;
class function TDataSampleXMLHandler12.GetXMLRootElementName: WideString;
begin
Result := 'Sample2'
end;
{ TDataSampleXMLHandler1 }
class function TDataSampleXMLHandler1.GetXMLClass: TClass;
begin
Result := TXMLSampleDataObj1;
end;
class function TDataSampleXMLHandler1.GetXMLIfType: TGUID;
begin
Result := IXMLDataSample1;
end;
class function TDataSampleXMLHandler1.GetXMLRootElementName: WideString;
begin
Result := 'Sample2';
end;
{ TXMLSampleDataObj1 }
function TXMLSampleDataObj1.GetXmlDataSample1: WideString;
begin
Result := ChildNodes['XmlDataSample1'].Text;
end;
procedure TXMLSampleDataObj1.SetXmlDataSample1(const Value: WideString);
begin
ChildNodes['XmlDataSample1'].NodeValue := Value;
end;
{ TXMLSampleDataObj2 }
function TXMLSampleDataObj2.GetXMLDataSample2: WideString;
begin
Result := ChildNodes['XmlDataSample2'].Text;
end;
procedure TXMLSampleDataObj2.SetXmlDataSample2(const Value: WideString);
begin
ChildNodes['XmlDataSample2'].NodeValue := Value;
end;
end.*
Saving a single XML node to a document is working well. But I want to add these nodes to an XML document the application stoppes, got no error. My problem here is:
procedure TForm3.btnXmlSaveToFileClick(Sender: TObject);
//Works well
vXML1 := TDataSampleXMLHandler1.NewXML;
vXML1.XmlDataSample1 := 'test data';
TDataSampleXMLHandler1.SaveXMLToFile(vXml1, 'C:\Teszt\XmlSample.XML');
//My problem here, cannot add IXMLNode to XMLDocument
vXMLDoc := NewXMLDocument;
vXMLDoc.ChildNodes.Add(vXML1);
//And add vXML2 and more...
vXMLDoc.SaveToFile('C:\Teszt\XmlDocSaveSAmple.XML');
end;
My finally XML what I want to looks like:
<?xml version="1.0"?>
<Sample2>
<XmlDataSample2>test data</XmlDataSample2>
</Sample2>
<Sample1>
<XmlDataSample1>test data</XmlDataSample1>
</Sample1>
Upvotes: 1
Views: 1630
Reputation: 596196
The XML standard allows only 1 top-level element in a document. You are going to have to make your <Sample... >
elements be children of another top-level element, eg:
<?xml version="1.0"?>
<Samples>
<Sample2>
<XmlDataSample2>test data</XmlDataSample2>
</Sample2>
<Sample1>
<XmlDataSample1>test data</XmlDataSample1>
</Sample1>
</Samples>
procedure TForm3.btnXmlSaveToFileClick(Sender: TObject);
var
vXMLDoc: IXMLDocument;
vXML1: IXMLDataSample1;
vXMLSamples: IXMLNode;
begin
vXML1 := TDataSampleXMLHandler1.NewXML;
vXML1.XmlDataSample1 := 'test data';
vXMLDoc := NewXMLDocument;
vXMLSamples := vXMLDoc.AddChild('Samples');
vXMLSamples.ChildNodes.Add(vXML1);
//And add vXML2 and more...
vXMLDoc.SaveToFile('C:\Teszt\XmlDocSaveSample.XML');
end;
Upvotes: 2