Author: Mike Shkolnik
How to generate the XML-file from linked dataset?
Answer:
Solve 1:
Sometimes in our development we must export a data from dataset into different
formats like MS Excel, Word, HTML, Text etc. Now in the Internet we have a new
popular format - XML-file. So for large part of applications we wants to include
the possibility of export into XML, of course. I want to demonstrate the sample of
one procedure for exporting of dataset's data into XML:
procedure DatasetToXML(Dataset: TDataset; FileName: string);
The first Dataset parameter is source dataset with data (your Table or Query
component, or some other third-party dataset). The second FileName parameter is a
name of target XML-file.
1 { SMExport suite's free demo
2 Data export from dataset into XML-file
3
4 Copyright(C) 2000, written by Scalabium, Shkolnik Mike
5 E-Mail: smexport@scalabium.com
6 mshkolnik@yahoo.com
7 WEB: http://www.scalabium.com
8 http://www.geocities.com/mshkolnik
9 }
10 unit DS2XML;
11
12 interface
13
14 uses
15 Classes, DB;
16
17 procedure DatasetToXML(Dataset: TDataset; FileName: string);
18
19 implementation
20
21 uses
22 SysUtils;
23
24 var
25 SourceBuffer: PChar;
26
27 procedure WriteString(Stream: TFileStream; s: string);
28 begin
29 StrPCopy(SourceBuffer, s);
30 Stream.write(SourceBuffer[0], StrLen(SourceBuffer));
31 end;
32
33 procedure WriteFileBegin(Stream: TFileStream; Dataset: TDataset);
34
35 function XMLFieldType(fld: TField): string;
36 begin
37 case fld.DataType of
38 ftString: Result := '"string" WIDTH="' + IntToStr(fld.Size) + '"';
39 ftSmallint: Result := '"i4"'; //??
40 ftInteger: Result := '"i4"';
41 ftWord: Result := '"i4"'; //??
42 ftBoolean: Result := '"boolean"';
43 ftAutoInc: Result := '"i4" SUBTYPE="Autoinc"';
44 ftFloat: Result := '"r8"';
45 ftCurrency: Result := '"r8" SUBTYPE="Money"';
46 ftBCD: Result := '"r8"'; //??
47 ftDate: Result := '"date"';
48 ftTime: Result := '"time"'; //??
49 ftDateTime: Result := '"datetime"';
50 else
51 end;
52 if fld.Required then
53 Result := Result + ' required="true"';
54 if fld.Readonly then
55 Result := Result + ' readonly="true"';
56 end;
57
58 var
59 i: Integer;
60 begin
61 WriteString(Stream,
62 '<?xml version="1.0" standalone="yes"?><!-- Generated by SMExport --> ' +
63 '<DATAPACKET Version="2.0">');
64 WriteString(Stream, '<METADATA><FIELDS>');
65
66 {write th metadata}
67 with Dataset do
68 for i := 0 to FieldCount - 1 do
69 begin
70 WriteString(Stream, '<FIELD attrname="' +
71 Fields[i].FieldName +
72 '" fieldtype=' +
73 XMLFieldType(Fields[i]) +
74 '/>');
75 end;
76 WriteString(Stream, '</FIELDS>');
77 WriteString(Stream, '<PARAMS DEFAULT_ORDER="1" PRIMARY_KEY="1" LCID="1033"/>');
78 WriteString(Stream, '</METADATA><ROWDATA>');
79 end;
80
81 procedure WriteFileEnd(Stream: TFileStream);
82 begin
83 WriteString(Stream, '</ROWDATA></DATAPACKET>');
84 end;
85
86 procedure WriteRowStart(Stream: TFileStream; IsAddedTitle: Boolean);
87 begin
88 if not IsAddedTitle then
89 WriteString(Stream, '<ROW');
90 end;
91
92 procedure WriteRowEnd(Stream: TFileStream; IsAddedTitle: Boolean);
93 begin
94 if not IsAddedTitle then
95 WriteString(Stream, '/>');
96 end;
97
98 procedure WriteData(Stream: TFileStream; fld: TField; AString: ShortString);
99 begin
100 if Assigned(fld) and (AString <> '') then
101 WriteString(Stream, ' ' + fld.FieldName + '="' + AString + '"');
102 end;
103
104 function GetFieldStr(Field: TField): string;
105
106 function GetDig(i, j: Word): string;
107 begin
108 Result := IntToStr(i);
109 while (Length(Result) < j) do
110 Result := '0' + Result;
111 end;
112
113 var
114 Hour, Min, Sec, MSec: Word;
115 begin
116 case Field.DataType of
117 ftBoolean: Result := UpperCase(Field.AsString);
118 ftDate: Result := FormatDateTime('yyyymmdd', Field.AsDateTime);
119 ftTime: Result := FormatDateTime('hhnnss', Field.AsDateTime);
120 ftDateTime:
121 begin
122 Result := FormatDateTime('yyyymmdd', Field.AsDateTime);
123 DecodeTime(Field.AsDateTime, Hour, Min, Sec, MSec);
124 if (Hour <> 0) or (Min <> 0) or (Sec <> 0) or (MSec <> 0) then
125 Result := Result + 'T' + GetDig(Hour, 2) + ':' + GetDig(Min, 2) + ':' +
126 GetDig(Sec, 2) + GetDig(MSec, 3);
127 end;
128 else
129 Result := Field.AsString;
130 end;
131 end;
132
133 procedure DatasetToXML(Dataset: TDataset; FileName: string);
134 var
135 Stream: TFileStream;
136 bkmark: TBookmark;
137 i: Integer;
138 begin
139 Stream := TFileStream.Create(FileName, fmCreate);
140 SourceBuffer := StrAlloc(1024);
141 WriteFileBegin(Stream, Dataset);
142
143 with DataSet do
144 begin
145 DisableControls;
146 bkmark := GetBookmark;
147 First;
148
149 {write a title row}
150 WriteRowStart(Stream, True);
151 for i := 0 to FieldCount - 1 do
152 WriteData(Stream, nil, Fields[i].DisplayLabel);
153 {write the end of row}
154 WriteRowEnd(Stream, True);
155
156 while (not EOF) do
157 begin
158 WriteRowStart(Stream, False);
159 for i := 0 to FieldCount - 1 do
160 WriteData(Stream, Fields[i], GetFieldStr(Fields[i]));
161 {write the end of row}
162 WriteRowEnd(Stream, False);
163
164 Next;
165 end;
166
167 GotoBookmark(bkmark);
168 EnableControls;
169 end;
170
171 WriteFileEnd(Stream);
172 Stream.Free;
173 StrDispose(SourceBuffer);
174 end;
175
176 end.
Solve 2:
there is a simpler way of saving the resultset in a xml-file...
drop a TClientDataSet and a TdataSetProvider on the form.
set the TDatasetProvider.dataset to point to your TQuery.
Set the TClientDataSet.ProviderName to point to the TDataSetProvider.
In the code write:
177
178 ClientDataSet.active := true;
179 ClentDataSet.SaveToFile('c: \results.xml');
as long as the type name of the file is xml, it will be a xml-file.
|