source: trunk/Packages/Common/XML.pas

Last change on this file was 8, checked in by chronos, 2 weeks ago
  • Fixed: Data tab populating and refreshing.
  • Fixed: Used currency as decimal type for measured values instead inaccurate double type.
File size: 10.2 KB
Line 
1unit XML;
2
3interface
4
5uses
6 {$IFDEF WINDOWS}Windows,{$ENDIF}
7 Classes, SysUtils, DateUtils, DOM, xmlread;
8
9function XMLTimeToDateTime(XMLDateTime: string): TDateTime;
10function DateTimeToXMLTime(Value: TDateTime; ApplyLocalBias: Boolean = True): string;
11procedure WriteInteger(Node: TDOMNode; Name: string; Value: Integer);
12procedure WriteInt64(Node: TDOMNode; Name: string; Value: Int64);
13procedure WriteBoolean(Node: TDOMNode; Name: string; Value: Boolean);
14procedure WriteString(Node: TDOMNode; Name: string; Value: string);
15procedure WriteDateTime(Node: TDOMNode; Name: string; Value: TDateTime);
16procedure WriteDouble(Node: TDOMNode; Name: string; Value: Double);
17procedure WriteCurrency(Node: TDOMNode; Name: string; Value: Currency);
18function ReadInteger(Node: TDOMNode; Name: string; DefaultValue: Integer): Integer;
19function ReadInt64(Node: TDOMNode; Name: string; DefaultValue: Int64): Int64;
20function ReadBoolean(Node: TDOMNode; Name: string; DefaultValue: Boolean): Boolean;
21function ReadString(Node: TDOMNode; Name: string; DefaultValue: string): string;
22function ReadDateTime(Node: TDOMNode; Name: string; DefaultValue: TDateTime): TDateTime;
23function ReadDouble(Node: TDOMNode; Name: string; DefaultValue: Double): Double;
24function ReadCurrency(Node: TDOMNode; Name: string; DefaultValue: Currency): Currency;
25procedure ReadXMLFileParser(out Doc: TXMLDocument; FileName: string);
26
27var
28 XmlFormatSettings: TFormatSettings = (
29 CurrencyFormat: 1;
30 NegCurrFormat: 5;
31 ThousandSeparator: ',';
32 DecimalSeparator: '.';
33 CurrencyDecimals: 2;
34 DateSeparator: '-';
35 TimeSeparator: ':';
36 ListSeparator: ',';
37 CurrencyString: '$';
38 ShortDateFormat: 'yyyy-mm-dd';
39 LongDateFormat: 'dd" "mmmm" "yyyy';
40 TimeAMString: 'AM';
41 TimePMString: 'PM';
42 ShortTimeFormat: 'hh:nn';
43 LongTimeFormat: 'hh:nn:ss';
44 ShortMonthNames: ('Jan','Feb','Mar','Apr','May','Jun',
45 'Jul','Aug','Sep','Oct','Nov','Dec');
46 LongMonthNames: ('January','February','March','April','May','June',
47 'July','August','September','October','November','December');
48 ShortDayNames: ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
49 LongDayNames: ('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
50 TwoDigitYearCenturyWindow: 50;
51 );
52
53
54implementation
55
56function ReadDouble(Node: TDOMNode; Name: string; DefaultValue: Double): Double;
57var
58 NewNode: TDOMNode;
59begin
60 Result := DefaultValue;
61 NewNode := Node.FindNode(DOMString(Name));
62 if Assigned(NewNode) then
63 Result := StrToFloat(string(NewNode.TextContent), XmlFormatSettings);
64end;
65
66function ReadCurrency(Node: TDOMNode; Name: string; DefaultValue: Currency
67 ): Currency;
68var
69 NewNode: TDOMNode;
70begin
71 Result := DefaultValue;
72 NewNode := Node.FindNode(DOMString(Name));
73 if Assigned(NewNode) then
74 Result := StrToCurr(string(NewNode.TextContent), XmlFormatSettings);
75end;
76
77procedure ReadXMLFileParser(out Doc: TXMLDocument; FileName: string);
78var
79 Parser: TDOMParser;
80 Src: TXMLInputSource;
81 InFile: TFileStream;
82begin
83 try
84 InFile := TFileStream.Create(FileName, fmOpenRead);
85 Src := TXMLInputSource.Create(InFile);
86 Parser := TDOMParser.Create;
87 Parser.Options.PreserveWhitespace := True;
88 Parser.Parse(Src, Doc);
89 finally
90 Src.Free;
91 Parser.Free;
92 InFile.Free;
93 end;
94end;
95
96function GetTimeZoneBias: Integer;
97{$IFDEF WINDOWS}
98var
99 TimeZoneInfo: TTimeZoneInformation;
100begin
101 {$push}{$warn 5057 off}
102 case GetTimeZoneInformation(TimeZoneInfo) of
103 TIME_ZONE_ID_STANDARD: Result := TimeZoneInfo.Bias + TimeZoneInfo.StandardBias;
104 TIME_ZONE_ID_DAYLIGHT: Result := TimeZoneInfo.Bias + TimeZoneInfo.DaylightBias;
105 else
106 Result := 0;
107 end;
108 {$pop}
109end;
110{$ELSE}
111begin
112 Result := 0;
113end;
114{$ENDIF}
115
116function LeftCutString(var Source: string; out Output: string; Delimiter: string; Allowed: string = ''): Boolean;
117var
118 I: Integer;
119 Matched: Boolean;
120begin
121 I := 1;
122 Matched := True;
123 while (I < Length(Source)) and Matched do begin
124 Matched := True;
125 if (Source[I] = Delimiter) then Matched := False;
126 //for J := 1 to Length(Allowed) do
127 // if Source[I] = Allowed[J] then Matched := True;
128 if Matched then Inc(I);
129 end;
130 if (Delimiter = Copy(Source, I, Length(Delimiter))) or (I = Length(Source)) then begin
131 Output := Copy(Source, 1, I - 1);
132 Delete(Source, 1, Length(Output) + Length(Delimiter));
133 Result := True;
134 end else begin
135 Output := '';
136 Result := False;
137 end;
138end;
139
140function XMLTimeToDateTime(XMLDateTime: string): TDateTime;
141var
142 Part: string;
143 Year: Integer;
144 Month: Integer;
145 Day: Integer;
146 Hour: Integer;
147 Minute: Integer;
148 Second: Integer;
149 SecondFraction: Double;
150 Millisecond: Integer;
151begin
152 if LeftCutString(XMLDateTime, Part, '-') then
153 Year := StrToInt(Part);
154 if LeftCutString(XMLDateTime, Part, '-') then
155 Month := StrToInt(Part);
156 if Pos('T', XMLDateTime) > 0 then begin
157 if LeftCutString(XMLDateTime, Part, 'T') then
158 Day := StrToInt(Part);
159 if LeftCutString(XMLDateTime, Part, ':') then
160 Hour := StrToInt(Part);
161 if LeftCutString(XMLDateTime, Part, ':') then
162 Minute := StrToInt(Part);
163 if Pos('.', XMLDateTime) > 0 then begin
164 if LeftCutString(XMLDateTime, Part, '.') then
165 Second := StrToInt(Part);
166 if Pos('+', XMLDateTime) > 0 then
167 LeftCutString(XMLDateTime, Part, '+') else
168 if Pos('-', XMLDateTime) > 0 then
169 LeftCutString(XMLDateTime, Part, '-') else
170 if Pos('Z', XMLDateTime) > 0 then
171 LeftCutString(XMLDateTime, Part, 'Z');
172 SecondFraction := StrToFloat('0' + DefaultFormatSettings.DecimalSeparator + Part);
173 Millisecond := Trunc(SecondFraction * 1000);
174 end else begin
175 if Pos('+', XMLDateTime) > 0 then
176 LeftCutString(XMLDateTime, Part, '+') else
177 if Pos('-', XMLDateTime) > 0 then
178 LeftCutString(XMLDateTime, Part, '-') else
179 if Pos('Z', XMLDateTime) > 0 then
180 LeftCutString(XMLDateTime, Part, 'Z');
181 Second := StrToInt(Part);
182 Millisecond := 0;
183 end;
184 end else begin
185 Day := StrToInt(XMLDateTime);
186 end;
187 Result := EncodeDateTime(Year, Month, Day, Hour, Minute, Second, Millisecond);
188 // TODO: Correct time by zone bias
189end;
190
191function DateTimeToXMLTime(Value: TDateTime; ApplyLocalBias: Boolean = True): string;
192const
193 Neg: array[Boolean] of string = ('+', '-');
194var
195 Bias: Integer;
196begin
197 Result := FormatDateTime('yyyy''-''mm''-''dd''T''hh'':''nn'':''ss''.''zzz', Value); { Do not localize }
198 Bias := GetTimeZoneBias;
199 if (Bias <> 0) and ApplyLocalBias then
200 begin
201 Result := Format('%s%s%.2d:%.2d', [Result, Neg[Bias > 0], { Do not localize }
202 Abs(Bias) div MinsPerHour,
203 Abs(Bias) mod MinsPerHour]);
204 end else
205 Result := Result + 'Z'; { Do not localize }
206end;
207
208procedure WriteInteger(Node: TDOMNode; Name: string; Value: Integer);
209var
210 NewNode: TDOMNode;
211begin
212 NewNode := Node.OwnerDocument.CreateElement(DOMString(Name));
213 NewNode.TextContent := DOMString(IntToStr(Value));
214 Node.AppendChild(NewNode);
215end;
216
217procedure WriteInt64(Node: TDOMNode; Name: string; Value: Int64);
218var
219 NewNode: TDOMNode;
220begin
221 NewNode := Node.OwnerDocument.CreateElement(DOMString(Name));
222 NewNode.TextContent := DOMString(IntToStr(Value));
223 Node.AppendChild(NewNode);
224end;
225
226procedure WriteBoolean(Node: TDOMNode; Name: string; Value: Boolean);
227var
228 NewNode: TDOMNode;
229begin
230 NewNode := Node.OwnerDocument.CreateElement(DOMString(Name));
231 NewNode.TextContent := DOMString(BoolToStr(Value));
232 Node.AppendChild(NewNode);
233end;
234
235procedure WriteString(Node: TDOMNode; Name: string; Value: string);
236var
237 NewNode: TDOMNode;
238begin
239 NewNode := Node.OwnerDocument.CreateElement(DOMString(Name));
240 NewNode.TextContent := DOMString(Value);
241 Node.AppendChild(NewNode);
242end;
243
244procedure WriteDateTime(Node: TDOMNode; Name: string; Value: TDateTime);
245var
246 NewNode: TDOMNode;
247begin
248 NewNode := Node.OwnerDocument.CreateElement(DOMString(Name));
249 NewNode.TextContent := DOMString(DateTimeToXMLTime(Value));
250 Node.AppendChild(NewNode);
251end;
252
253procedure WriteDouble(Node: TDOMNode; Name: string; Value: Double);
254var
255 NewNode: TDOMNode;
256begin
257 NewNode := Node.OwnerDocument.CreateElement(DOMString(Name));
258 NewNode.TextContent := DOMString(FloatToStr(Value, XmlFormatSettings));
259 Node.AppendChild(NewNode);
260end;
261
262procedure WriteCurrency(Node: TDOMNode; Name: string; Value: Currency);
263var
264 NewNode: TDOMNode;
265begin
266 NewNode := Node.OwnerDocument.CreateElement(DOMString(Name));
267 NewNode.TextContent := DOMString(CurrToStr(Value, XmlFormatSettings));
268 Node.AppendChild(NewNode);
269end;
270
271function ReadInteger(Node: TDOMNode; Name: string; DefaultValue: Integer): Integer;
272var
273 NewNode: TDOMNode;
274begin
275 Result := DefaultValue;
276 NewNode := Node.FindNode(DOMString(Name));
277 if Assigned(NewNode) then
278 Result := StrToInt(string(NewNode.TextContent));
279end;
280
281function ReadInt64(Node: TDOMNode; Name: string; DefaultValue: Int64): Int64;
282var
283 NewNode: TDOMNode;
284begin
285 Result := DefaultValue;
286 NewNode := Node.FindNode(DOMString(Name));
287 if Assigned(NewNode) then
288 Result := StrToInt64(string(NewNode.TextContent));
289end;
290
291function ReadBoolean(Node: TDOMNode; Name: string; DefaultValue: Boolean): Boolean;
292var
293 NewNode: TDOMNode;
294begin
295 Result := DefaultValue;
296 NewNode := Node.FindNode(DOMString(Name));
297 if Assigned(NewNode) then
298 Result := StrToBool(string(NewNode.TextContent));
299end;
300
301function ReadString(Node: TDOMNode; Name: string; DefaultValue: string): string;
302var
303 NewNode: TDOMNode;
304begin
305 Result := DefaultValue;
306 NewNode := Node.FindNode(DOMString(Name));
307 if Assigned(NewNode) then
308 Result := string(NewNode.TextContent);
309end;
310
311function ReadDateTime(Node: TDOMNode; Name: string; DefaultValue: TDateTime
312 ): TDateTime;
313var
314 NewNode: TDOMNode;
315begin
316 Result := DefaultValue;
317 NewNode := Node.FindNode(DOMString(Name));
318 if Assigned(NewNode) then
319 Result := XMLTimeToDateTime(string(NewNode.TextContent));
320end;
321
322end.
Note: See TracBrowser for help on using the repository browser.