将 TFDMemTable 数据追加到一个 XML 文件中
Append TFDMemTable data into one XML file
有没有办法将多个查询的所有数据库记录和结构保存到一个XML文件中?
我做的是:
procedure CopyRecords(Sender: TObject);
begin
try
TFDQuery.SQL.Text := 'SELECT * FROM SAMPLE_TABLE1';
TFDQuery.FetchOptions.Unidirectional := False;
TFDQuery.Open;
TFDQuery.FetchAll;
TFDmemtable.Data := DM.qry_SQL.Data;
TFDmemtable.First;
while not TFDmemtable.Eof do
begin
TFDmemtable.Edit;
TFDmemtable.Post;
TFDmemtable.Next;
end;
TFDmemtable.SaveToFile('C:\Test.xml', sfXML);
finally
TFDmemtable.Close;
end;
end;
这对于一个查询来说工作正常,但如果我更改 SQL 文本并保留文件名,内容将被覆盖。我想更改查询 (SQL.text) 并将所有查询数据保存到 one XML 文件中。
TFDQuery.SQL.Text := 'SELECT * FROM SAMPLE_TABLE1';
... save ...
TFDQuery.SQL.Text := 'SELECT * FROM SAMPLE_TABLE2';
... save (append) ...
如果您想 create/append 到您所描述的 Xml 文件,您实际上不需要
需要使用 FDMemTable。您可以直接从 FDQuery 执行如下所示的操作。
基本上你会看到的
- 以 XML 格式将 TFDQuery 保存到 TStringStream;
- 将 StringStream 的内容加载到 XmlDocument 对象中,使用
Windows' MSXML DOM 解析器;
- 将以前保存的查询的 XML 文件加载到第二个 Xml 文档中;和
- 将
Table
节点的内容从保存的查询复制到
第二个 Xml文档并保存文档。
代码:
uses
Data.DB, ADOInt, Data.Win.ADODB, Vcl.StdCtrls, Vcl.Grids, Vcl.DBGrids,
System.Classes, SysUtils, Variants, Vcl.Forms, Vcl.Controls, Vcl.ExtCtrls, Vcl.DBCtrls,
FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.UI.Intf,
FireDAC.Phys.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async,
FireDAC.Phys, FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf,
FireDAC.DApt, FireDAC.Comp.DataSet, FireDAC.Comp.Client, FireDAC.Phys.MSSQL,
FireDAC.Phys.MSSQLDef, FireDAC.VCLUI.Wait, FireDAC.Comp.UI,
Dialogs, FireDAC.Stan.StorageXML, WinApi.MSXMLIntf, WinApi.MSXML;
type
TForm1 = class(TForm)
DataSource1: TDataSource;
DBNavigator1: TDBNavigator;
DBGrid1: TDBGrid;
FDConnection1: TFDConnection;
FDQuery1: TFDQuery;
FDGUIxWaitCursor1: TFDGUIxWaitCursor;
Button1: TButton;
Memo1: TMemo;
FDStanStorageXMLLink1: TFDStanStorageXMLLink; // This is needed to save the Query to XML
[...]
protected
procedure SaveToXML(FDQuery: TFDQuery);
end;
const
scSavedData = 'D:\delphi\code\firedac\SavedData.Xml';
scSavedSingleQuery = 'D:\delphi\code\firedac\SavedSingleQuery.Xml';
scSavedDataXML = '<?xml version="1.0" encoding="utf-8"?><Data/>';
procedure TForm1.SaveToXML(FDQuery: TFDQuery);
var
SS : TStringStream;
XmlDoc1,
XMlDoc2 : IXMLDOMDocument2;
NodeList: IXmlDomNodeList;
nSource: IXmlDomNode;
nDestination : IXmlDomNode;
eDestination : IXmlDomElement;
begin
SS := TStringStream.Create;
XmlDoc1 := CoDomDocument.Create;
try
FDQuery.SaveToStream(SS, sfXML);
XmlDoc1.loadXML(SS.DataString);
NodeList := XmlDoc1.documentElement.selectNodes('//FDBS/Manager/TableList/Table');
nSource := NodeList.item[0];
// At this point, nSource is the XML node which contains the data + metadata
// of the FDQuery's result set
// Next we splice it into an XML file of previously saved FDQuery result sets
// or create this file if it doesn't already exist
XmlDoc2 := CoDomDocument.Create;
if FileExists(scSavedData) then begin
XmlDoc2.load(scSavedData)
end
else begin
XmlDoc2.loadXML(scSavedDataXML);
end;
nDestination := nSource.cloneNode(True) as IXmlDomNode;
XmlDoc2.documentElement.appendChild(nDestination);
eDestination := nDestination as IXmlDomElement;
eDestination.setAttribute('Sql', FDQuery.SQL.Text);
Memo1.Lines.Text := XmlDoc2.documentElement.Xml;
XmlDoc2.save(scSavedData);
finally
SS.Free; // Only this needs to be freed
// all the other (interface) objects will be finalized as the procedure exits
end;
end;
有没有办法将多个查询的所有数据库记录和结构保存到一个XML文件中?
我做的是:
procedure CopyRecords(Sender: TObject);
begin
try
TFDQuery.SQL.Text := 'SELECT * FROM SAMPLE_TABLE1';
TFDQuery.FetchOptions.Unidirectional := False;
TFDQuery.Open;
TFDQuery.FetchAll;
TFDmemtable.Data := DM.qry_SQL.Data;
TFDmemtable.First;
while not TFDmemtable.Eof do
begin
TFDmemtable.Edit;
TFDmemtable.Post;
TFDmemtable.Next;
end;
TFDmemtable.SaveToFile('C:\Test.xml', sfXML);
finally
TFDmemtable.Close;
end;
end;
这对于一个查询来说工作正常,但如果我更改 SQL 文本并保留文件名,内容将被覆盖。我想更改查询 (SQL.text) 并将所有查询数据保存到 one XML 文件中。
TFDQuery.SQL.Text := 'SELECT * FROM SAMPLE_TABLE1';
... save ...
TFDQuery.SQL.Text := 'SELECT * FROM SAMPLE_TABLE2';
... save (append) ...
如果您想 create/append 到您所描述的 Xml 文件,您实际上不需要 需要使用 FDMemTable。您可以直接从 FDQuery 执行如下所示的操作。
基本上你会看到的
- 以 XML 格式将 TFDQuery 保存到 TStringStream;
- 将 StringStream 的内容加载到 XmlDocument 对象中,使用 Windows' MSXML DOM 解析器;
- 将以前保存的查询的 XML 文件加载到第二个 Xml 文档中;和
- 将
Table
节点的内容从保存的查询复制到 第二个 Xml文档并保存文档。
代码:
uses
Data.DB, ADOInt, Data.Win.ADODB, Vcl.StdCtrls, Vcl.Grids, Vcl.DBGrids,
System.Classes, SysUtils, Variants, Vcl.Forms, Vcl.Controls, Vcl.ExtCtrls, Vcl.DBCtrls,
FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.UI.Intf,
FireDAC.Phys.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async,
FireDAC.Phys, FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf,
FireDAC.DApt, FireDAC.Comp.DataSet, FireDAC.Comp.Client, FireDAC.Phys.MSSQL,
FireDAC.Phys.MSSQLDef, FireDAC.VCLUI.Wait, FireDAC.Comp.UI,
Dialogs, FireDAC.Stan.StorageXML, WinApi.MSXMLIntf, WinApi.MSXML;
type
TForm1 = class(TForm)
DataSource1: TDataSource;
DBNavigator1: TDBNavigator;
DBGrid1: TDBGrid;
FDConnection1: TFDConnection;
FDQuery1: TFDQuery;
FDGUIxWaitCursor1: TFDGUIxWaitCursor;
Button1: TButton;
Memo1: TMemo;
FDStanStorageXMLLink1: TFDStanStorageXMLLink; // This is needed to save the Query to XML
[...]
protected
procedure SaveToXML(FDQuery: TFDQuery);
end;
const
scSavedData = 'D:\delphi\code\firedac\SavedData.Xml';
scSavedSingleQuery = 'D:\delphi\code\firedac\SavedSingleQuery.Xml';
scSavedDataXML = '<?xml version="1.0" encoding="utf-8"?><Data/>';
procedure TForm1.SaveToXML(FDQuery: TFDQuery);
var
SS : TStringStream;
XmlDoc1,
XMlDoc2 : IXMLDOMDocument2;
NodeList: IXmlDomNodeList;
nSource: IXmlDomNode;
nDestination : IXmlDomNode;
eDestination : IXmlDomElement;
begin
SS := TStringStream.Create;
XmlDoc1 := CoDomDocument.Create;
try
FDQuery.SaveToStream(SS, sfXML);
XmlDoc1.loadXML(SS.DataString);
NodeList := XmlDoc1.documentElement.selectNodes('//FDBS/Manager/TableList/Table');
nSource := NodeList.item[0];
// At this point, nSource is the XML node which contains the data + metadata
// of the FDQuery's result set
// Next we splice it into an XML file of previously saved FDQuery result sets
// or create this file if it doesn't already exist
XmlDoc2 := CoDomDocument.Create;
if FileExists(scSavedData) then begin
XmlDoc2.load(scSavedData)
end
else begin
XmlDoc2.loadXML(scSavedDataXML);
end;
nDestination := nSource.cloneNode(True) as IXmlDomNode;
XmlDoc2.documentElement.appendChild(nDestination);
eDestination := nDestination as IXmlDomElement;
eDestination.setAttribute('Sql', FDQuery.SQL.Text);
Memo1.Lines.Text := XmlDoc2.documentElement.Xml;
XmlDoc2.save(scSavedData);
finally
SS.Free; // Only this needs to be freed
// all the other (interface) objects will be finalized as the procedure exits
end;
end;