Database table to XML and back - Amin_Mansouri - 08-30-2011
در اين آموزش درباره ايجاد فايل ايكس ام ال با خواندن اطلاعات از جدول پارادوكس و همچنين درج اطلاعات يكسان داخل جدول از اطلاعات خوانده شده از فايل ايكس ام ال (يا هر ديتابيسي كه در دلفي در دسترس شماست) بحث خواهيم كرد. اين كد براي جدول ها با فيلد Memo كار نخواهد كرد . ما از MS XML Parser براي تجزيه سند ايكس ام ال استفاده مي كنيم بنابراين بايد IE5.0 يا ورژن جديدتر آن را روي سيستم خود نصب داشته باشيد .
ايجاد يك فايل ايكس ام ال – از ديتابيسك به ايكس ام ال
براي فايل ايكس ام ال از قرارداد زير پيروي مي كنيم :
1- نام اصلي فايل ايكس ام ال يكسان با نام جدول است .
2- هر ركورد از جدول در بين تگ ها (Tag) وارد مي شود .
3- دادهاي هر رديف از جدول در بين تگ ها وارد مي شوند .
براي مثال :
کد: Argentina
Buenos Aires
South America
2777815
32300003
...
آماده كرد يك پروژه دلفي
برنامه جديد رو با قراردادن يك دكمه و يك كامپوننت Table بر روي فرم اصلي برنامه شروع كنيد .
خاصيت هاي Table را به شرح زير تنظيم كنيد .
کد: Name = Table1
DatabaseName = DBDEMOS
TableName = Country
Active = True
از منوي Project گزينه Import Type library انتخاب كنيد . در پنجره ظاهر شده گزينه "Microsoft XML,Version 2.0(version 2.0)" را از ليست انتخاب و روي دكمه "Create Unit" كليك كنيد. يونيت MSXML_TLB به پروژه شما اضافه خواهد شد .
MSXML_TLB در بخش uses يونيت خودتون اضافه كنيد .
متغيرهاي زير را در بخش Var معرفي كنيد :
کد: DataList : TStringlist;
doc : IXMLDOMDocument;
root, child, child1 : IXMLDomElement;
text1, text2 : IXMLDOMText;
nlist : IXMLDOMNodelist;
dataRecord : String;
فانكشن زير را به يونيت خود اضافه كنيد . فانكش makeXml فايل ايكس ام ال را با خواندن اطلاعات انتخابي از جدول (Country) ايجاد مي كند .
کد: function TForm1.makeXml(table: TTable): Integer;
var
i : Integer;
xml,temp : String;
begin
try
table.close;
table.open;
xml := table.TableName;
doc := CreateOleObject('Microsoft.XMLDOM')
as IXMLDomDocument;
//Set the root name of the xml
file as that of the table name.
//In this case "country"
root := doc.createElement(xml);
doc.appendchild(root);
//This while loop will go through the
entire table to generate the xml file
while not table.eof do begin
//adds the first level children , Records
child:= doc.createElement('Records');
root.appendchild(child);
for i:=0 to table.FieldCount-1 do begin
//adds second level children
child1 := doc.createElement
(table.Fields[i].FieldName);
child.appendchild(child1);
//Check field types
case TFieldType
(Ord(table.Fields[i].DataType)) of
ftString:
begin
if Table.Fields[i].AsString ='' then
temp :='null' //Put a default string
else
temp := table.Fields[i].AsString;
end;
ftInteger, ftWord, ftSmallint:
begin
if Table.Fields[i].AsInteger > 0 then
temp := IntToStr(table.Fields[i].AsInteger)
else
temp := '0';
end;
ftFloat, ftCurrency, ftBCD:
begin
if table.Fields[i].AsFloat > 0 then
temp := FloatToStr(table.Fields[i].AsFloat)
else
temp := '0';
end;
ftBoolean:
begin
if table.Fields[i].Value then
temp:= 'True'
else
temp:= 'False';
end;
ftDate:
begin
if (not table.Fields[i].IsNull) or
(Length(Trim(table.Fields[i].AsString))
> 0) then
temp := FormatDateTime
('MM/DD/YYYY',
table.Fields[i].AsDateTime)
else
//put a valid default date
temp:= '01/01/2000';
end;
ftDateTime:
begin
if (not table.Fields[i].IsNull) or
(Length(Trim(table.Fields[i].AsString))
> 0) then
temp := FormatDateTime
('MM/DD/YYYY hh:nn:ss',
table.Fields[i].AsDateTime)
else
//Put a valid default date and time
temp := '01/01/2000 00:00:00';
end;
ftTime:
begin
if (not table.Fields[i].IsNull) or
(Length(Trim(table.Fields[i].AsString))
> 0) then
temp := FormatDateTime
('hh:nn:ss',
table.Fields[i].AsDateTime)
else
//Put a valid default time
temp := '00:00:00';
end;
end;
child1.appendChild(doc.createTextNode(temp));
end;
table.Next;
end;
doc.save(xml+'.xml');
memo1.lines.Append(doc.xml);
Result:=1;
except
on e:Exception do
Result:=-1;
end;
end;
اين فانكشن را در رويداد OnClick دكمه فراخواني كنيد :
procedure TForm1.Button1Click(Sender: TObject);
begin
if makeXml(table1)=1 then
showmessage('XML Generated')
else
showmessage('Error while generating XML File');
end;
اگر فايل ايكس ام ال ايجاد شده (country.xml) را در IE باز كنيد بايد چيزي شبيه به كد زير را مشاهده كنيد :
Argentina
Buenos Aires
South America
2777815
32300003
Bolivia
La Paz
South America
1098575
7300000
...
Venezuela
Caracas
South America
912047
19700000
از ايكس ام ال به ديتابيس
شما فايل ايكس ام ال را از دادهاي موجود در جدول كشور ايجاد كرديد . از طرفي دادها در فايل ايكس ام ال ايجاد شده و جدول كشور يكسان هستند. اگر سعي كنيد دادهاي جدول كشور را بدون حذف دادهاي قبلي موجود در جدول از فايل ايكس ام ال ايجاد شده پر كنيد با خطاي "Primary key violation" روبرو خواهيد شد . بنابراين بايد قبل از ادامه كدهاي زير همه دادهاي موجود در جدول كشور را حذف كنيد .
دكمه ديگري را با نام (Button2) و يك Memo در فرم اصلي اضافه كنيد . كد بعدي را در رويداد OnClick دكمه Button2 اضافه كنيد . Memo براي نمايش وضعيت ايجاد ركوردها مي باشد .
کد: procedure TForm1.Button2Click(Sender: TObject);
var
i,ret_val,count : Integer;
strData : String;
begin
{
Before inserting data in to the country table,
make sure that the data in the generated xml
file (country.xml) and country table (DBDEMOS)
are different.
}
try
count:=1;
DataList:=TStringList.Create;
memo1.Clear;
doc := CreateOleObject('Microsoft.XMLDOM')
as IXMLDomDocument;
//Load country.xml file
doc.load('country.xml');
nlist:=doc.getElementsByTagName('Records');
memo1.lines.append('Table Name :country');
memo1.lines.append('---------------------');
for i:=0 to nlist.Get_length-1 do begin
travelChildren
(nlist.Get_item(i).Get_childNodes);
//Removes the first character(,)
//from 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:Exception do
Showmessage(e.message);
end;
end;
نكته : متغير nlist شما ليستي از node ها مي باشد . در برنامه مثال ما اولين node به اين شرح است :
...
Argentina
Buenos Aires
South America
2777815
32300003
...
ما ليست Node ها را به فانكشن travelchildren (تابع بازگشتي) پاس مي كنيم . در اين فانكشن دادها به صورت رشته اي استخراج و به يك متغير TStringList اضافه مي شوند . در نهايت هم اين ليست رشته ها (StringList) به فانكشن insertintotable پاس شده و ركوردها يكي يكي به جدول كشور اضافه خواهند شد .
کد: procedure TForm1.travelChildren
(nlist1:IXMLDOMNodeList);
var
j:Integer;
temp:String;
begin
for j:=0 to nlist1.Get_length-1 do begin
//node type 1 means an entity
//and node type 5 means 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)
//node Type 3 means a text node,
//ie you find the data
else if(nlist1.Get_item(j).Get_nodeType=3) then
begin
temp:= trim(nlist1.Get_item(j).Get_nodeValue);
//this is for displaying a
//single record on the memo
dataRecord:=dataRecord+','+temp;
//Datalist will contain one record
//after completing one full travel
//through the node list
DataList.Add(temp);
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 - 1 do begin
table1.Fields[i].AsVariant:= stpt[i];
end;
try
table1.post;
result:=1;
except
on E:Exception do
result:=-1;
end;
end;
نتيجه گيري
كد فرم اين مبحث آموزشي را با كليك اينجا دانلود كنيد
لینک سورس کد :
http://delphi.about.com/library/bluc/text/code/xmldelphi.zip
. مي توانيد اين برنامه را براي هر ديتابيسي ايجاد كنيد . همچنين مي توانيد دادها را بين فايل ايكس ام ال و يك شبكه (يا روي اينترنت) انتقال دهيد يا يك ديتابيس را بروزرساني كنيد .
|