再转一个文章吧:
用XML文件作数据库转换中介
转贴自:http://www.gois.ws
本文说明如何从一个Paradox数据库读取数据,生成XML文件,然后将XML文件中的数据插入到一个新的表中。这个新的数据库表可以还是Paradox,也可以是任何Delphi能够访问的数据库。我使用MSXML来解析XML文件,因此你必须使用IE 5.0以上才能使用我的代码。
生成XML文件
转换生成XML文件的过程如下。
XML文件的根名字与表名相同(本例是"country")。
标记<Records>和</Records>之间是各个纪录。
XML中节点元素标记<Field Name>和</Field Name>之间是数据。
<country>
<Records>
<Name>Argentina</Name>
<Capital>Buenos Aires</Capital>
<Continent>South America</Continent>
<Area>2777815</Area>
<Population>32300003</Population>
</Records>
.
.
</country>
启动一个新应用(application),在主窗口(Main Form)中加入按钮(TButton)和表(TTable)控件。Tabled的设置如下:
DatabaseName : DBDEMOS
Name : Table1
TableName : country (不要后缀 ".db")
Active : True
选择主菜单Project/Import,导入数据库类型。
选择"Microsoft XML, Version 2.0 (version 2.0)",然后点击"Create Unit"按钮。此后,就有一个MSXML_TLB增加到你的工程(project)文件中。要在unit文件的interface段的uses说明里加上MSXML_TLB。
在变量声明中作如下声明:
DataList : TStringlist;
doc : IXMLDOMDocument;
root, child, child1 : IXMLDomElement;
text1, text2 : IXMLDOMText;
nlist : IXMLDOMNodelist;
dataRecord : String;
在执行部分加入以下代码,这就可以从country表中读取数据并生成XML文件。
function TForm1.makeXml(table:TTable):Integer;
var
i : Integer;
xml : String;
begin
try
table.close;
table.open;
xml := table.TableName;
do
c := CreateOleObject('Microsoft.XMLDOM') as IXMLDomDocument;
// 设置XML文件的根名字为"country",与表名相同。
root :=do
c.createElement(xml);
// 把根节点加入到文件中
do
c.appendchild(root);
// 循环产生整个XML文件
while not table.eofdo
begin
// 加入第一级子节点,即纪录
child:=do
c.createElement('Records');
root.appendchild(child);
// 加入第二级子节点
for i:=0 to table.FieldCount-1do
begin
child1:=doc.createElement(table.Fields.FieldName);
child1.appendChild(doc.createTextNode(table.Fields.value));
child.appendchild(child1);
end;
table.Next;
end;
do
c.save(xml+'.xml');
Result:=1;
except
on e:Exceptiondo
Result:=-1;
end;
end;
Call the function in Button1's click event:
procedure TForm1.Button1Click(Sender: TObject);
begin
if makeXml(table1)=1 then
showmessage('XML Generated')
else
showmessage('Error while generating XML File');
end;
随后用IE浏览器打开XML文件(country.xml),就能看到如下结果:
<country>
<Records>
<Name>Argentina</Name>
<Capital>Buenos Aires</Capital>
<Continent>South America</Continent>
<Area>2777815</Area>
<Population>32300003</Population>
</Records>
<Records>
<Name>Bolivia</Name>
<Capital>La Paz</Capital>
<Continent>South America</Continent>
<Area>1098575</Area>
<Population>7300000</Population>
</Records>
.
.
<Records>
<Name>Venezuela</Name>
<Capital>Caracas</Capital>
<Continent>South America</Continent>
<Area>912047</Area>
<Population>19700000</Population>
</Records>
</country>
生成新表
XML文件中的数据与原表的数据完全一样。如果直接将数据插入回原表,会导致主索引出错。所以如果真想这么作得话,要事先删除原表。
在主窗口上增加另一个按钮和一个memo控件。为第二个按钮填写以下onclick事件代码。(memo用于显示数据插入成功与否的信息)。
procedure TForm1.Button2Click(Sender: TObject);
var
i,ret_val,count:Integer;
strData:String;
begin
// 注意:在向country表插入数据前,确认XML文件中的数据与原表数据是不同的。或者作一个新表。
try
count:=1;
DataList:=TStringList.Create;
memo1.Clear;
do
c := CreateOleObject('Microsoft.XMLDOM') as IXMLDomDocument;
// 加载country.xml文件
do
c.load('country.xml');
nlist:=doc.getElementsByTagName('Records');
memo1.lines.append('Table Name :country');
memo1.lines.append('---------------------');
for i:=0 to nlist.Get_length-1do
begin
travelChildren(nlist.Get_item(i).Get_childNodes);
// 从dataRecord中滤掉第一个","
strData:=copy(dataRecord,2,length(dataRecord));
memo1.lines.append(strData);
dataRecord:='';
ret_val:=insertintotable(Datalist);
if ret_val=1 then
memo1.lines.append('Data inserted successfully.............!')
else
if ret_val=-1 then
memo1.lines.append('Error while updating.....Try again.....!');
memo1.lines.append('=============================================' + '==(Record no. :'+inttostr(count)+')');
DataList.Clear;
count:=count+1;
end;
except
on e:Exceptiondo
Showmessage(e.message);
end;
end;
nlist是节点列表。在本例中,第一个节点是:
<Records>
<Name>Argentina</Name>
<Capital>Buenos Aires</Capital>
<Continent>South America</Continent>
<Area>2777815</Area>
<Population>32300003</Population>
</Records>
我们用travelchildren函数来解析节点。它用递归方式遍历节点列表,直到找到一个文本节点。这个文本数据被加入到TStringlist(Datalist)。第一次遍历完成后,可以在Datalist看到里看到Argentina, Buenos Aires, South America, 2777815, 32300003等字符串。然后把这个字符串传递给insertintotable函数,让它在country表中插入一条纪录。循环这个过程直至完成遍历整个XML文件。
procedure TForm1.travelChildren(nlist1:IXMLDOMNodeList);
var
j:Integer;
temp:String;
begin
for j:=0 to nlist1.Get_length-1do
begin
// 节点类型1表示是一个实体(entity),节点类型5表示EntityRef
if((nlist1.Get_item(j).Get_nodeType= 1) or (nlist1.Get_item(j).Get_nodeType=5)) then
travelChildren(nlist1.Get_item(j).Get_childNodes)
// 节点类型3表示文本节点,即找到数据
else
if(nlist1.Get_item(j).Get_nodeType=3) then
begin
temp:= trim(nlist1.Get_item(j).Get_nodeValue);
dataRecord:=dataRecord+','+temp;
//在memo显示一条纪录
DataList.Add(temp);
// 完成一次节点扫描后包含一条纪录的信息list.
end
end;
end;
function TForm1.insertintotable(stpt:TStringList):Integer;
var
I:Integer;
begin
table1.close;
table1.open;
table1.Insert;
for I := 0 to stpt.Count - 1do
table1.Fields.AsVariant:=stpt;
try
table1.post;
result:=1;
except
on E:Exceptiondo
result:=-1;
end;
end;
这个程序可以用于任何数据库,因此数据能以XML文件形式在网络(或者在互联网)上传递,实现远程更新。
如有问题,可与我联系。
转贴自:http://www.gois.ws