-
Notifications
You must be signed in to change notification settings - Fork 9
/
SimpleXML.pas
5061 lines (4467 loc) · 131 KB
/
SimpleXML.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
unit SimpleXML;
interface
uses
Windows, SysUtils, Classes;
const
BINXML_USE_WIDE_CHARS = 1;
XSTR_NULL = '{{null}}';
NODE_INVALID = $00000000;
NODE_ELEMENT = $00000001;
NODE_ATTRIBUTE = $00000002;
NODE_TEXT = $00000003;
NODE_CDATA_SECTION = $00000004;
NODE_ENTITY_REFERENCE = $00000005;
NODE_ENTITY = $00000006;
NODE_PROCESSING_INSTRUCTION = $00000007;
NODE_COMMENT = $00000008;
NODE_DOCUMENT = $00000009;
NODE_DOCUMENT_TYPE = $0000000A;
NODE_DOCUMENT_FRAGMENT = $0000000B;
NODE_NOTATION = $0000000C;
{$if CompilerVersion < 20}
type
UnicodeString = WideString;
RawByteString = AnsiString;
PByte = PAnsiChar;
{$ifend}
type
IXmlDocument = interface;
IXmlElement = interface;
IXmlText = interface;
IXmlCDATASection = interface;
IXmlComment = interface;
IXmlProcessingInstruction = interface;
// IXmlBase - áàçîâûé èíòåðôåéñ äëÿ âñåõ èíòåðôåéñîâ SimpleXML.
IXmlBase = interface
// GetObject - âîçâðàùàåò ññûëêó íà îáúåêò, ðåàëèçóþùèé èíòåðôåéñ.
function GetObject: TObject;
end;
// IXmlNameTable - òàáëèöà èìåí. Êàæäîìó èìåíè ñîïîñòàâëÿåòñÿ íåêèé
// óíèêàëüíûé ÷èñëîâîé èäåíòèôèêàòîð. Èñïîëüçóåòñÿ äëÿ õðàíåíèÿ
// íàçâàíèé òýãîâ è àòðèáóòîâ.
IXmlNameTable = interface(IXmlBase)
// GetID - âîçâðàùàåò ÷èñëîâîé èäåíòèôèêàòîð óêàçàííîé ñòðîêè.
function GetID(const aName: String): Integer;
// GetID - âîçâðàùàåò ñòðîêó, ñîîòâåòñòâóþùóþ óêàçàííîìó ÷èñëîâîìó
// èäåíòèôèêàòîðó.
function GetName(anID: Integer): String;
end;
IXmlNode = interface;
TXmlCompareNodes = function(const aNode1, aNode2: IXmlNode): Integer;
// IXmlNodeList - ñïèñîê óçëîâ. Ñïèñîê îðãàíèçîâàí â âèäå ìàññèâà.
// Äîñòóï ê ýëåìåíòàì ñïèñêà ïî èíäåêñó
IXmlNodeList = interface(IXmlBase)
// Get_Count - êîëè÷åñòâî óçëîâ â ñïèñêå
function Get_Count: Integer;
// Get_Item - ïîëó÷èòü óçåë ïî èíäåêñó
function Get_Item(anIndex: Integer): IXmlNode;
// Get_XML - âîçâðàùàåò ïðåäñòàâëåíèå ýëåìåíòîâ ñïèñêà â ôîðìàòå XML
function Get_XML: String;
procedure SortElements(aCompare: TXmlCompareNodes);
function IndexOf(const aNode: IXmlNode): Integer;
procedure Add(const aNode: IXmlNode);
procedure Insert(const aNode: IXmlNode; anIndex: Integer);
function Remove(const aNode: IXmlNode): Integer;
procedure Delete(anIndex: Integer);
procedure Clear;
property Count: Integer read Get_Count;
property Item[anIndex: Integer]: IXmlNode read Get_Item; default;
property XML: String read Get_XML;
end;
// IXmlNode - óçåë XML-äåðåâà
IXmlNode = interface(IXmlBase)
function Get_SourceLine: Integer;
function Get_SourceCol: Integer;
// Get_NameTable - òàáëèöà èìåí, èñïîëüçóåìàÿ äàííûì óçëîì
function Get_NameTable: IXmlNameTable;
// Get_NodeName - âîçâðàùàåò íàçâàíèå óçëà. Èíòåðïðåòàöèÿ íàçâàíèÿ óçëà
// çàâèñèò îò åãî òèïà
function Get_NodeName: String;
// Get_NodeNameID - âîçâðàùàåò êîä íàçâàíèÿ óçëà
function Get_NodeNameID: Integer;
// Get_NodeType - âîçâðàùàåò òèï óçëà
function Get_NodeType: Integer;
// Get_Text - âîçâðàùàåò òåêñò óçëà
function Get_Text: String;
// Set_Text - èçìåíÿåò òåêñò óçëà
procedure Set_Text(const aValue: String);
// Get_DataType - âîçàðàùàåò òèï äàííûõ óçëà â òåðìèíàõ âàðèàíòîâ
function Get_DataType: Integer;
// Get_TypedValue - âîçâðàùàåò
function Get_TypedValue: Variant;
// Set_TypedValue - èçìåíÿåò òåêñò óçëà íà òèïèçèðîâàííîå çíà÷åíèå
procedure Set_TypedValue(const aValue: Variant);
// Get_XML - âîçâðàùàåò ïðåäñòàâëåíèå óçëà è âñåõ âëîæåííûõ óçëîâ
// â ôîðìàòå XML.
function Get_XML: String;
// CloneNode - ñîçäàåò òî÷íóþ êîïèþ äàííîãî óçëà
// Åñëè çàäàí ïðèçíàê aDeep, òî ñîçäàñòñÿ êîïèÿ
// âñåé âåòâè èåðàðõèè îò äàííîãî óçëà.
function CloneNode(aDeep: Boolean = True): IXmlNode;
// Get_ParentNode - âîçâðàùàåò ðîäèòåëüñêèé óçåë
function Get_ParentNode: IXmlNode;
// Get_OwnerDocument - âîçâðàùàåò XML-äîêóìåíò,
// â êîòîðîì ðàñïîëîæåí äàííûé óçåë
function Get_OwnerDocument: IXmlDocument;
function Get_NextSibling: IXmlNode;
// Get_ChildNodes - âîçâðàùàåò ñïèñîê äî÷åðíèõ óçëîâ
function Get_ChildNodes: IXmlNodeList;
// AppendChild - äîáàâëÿåò óêàçàííûé óçåë â êîíåö ñïèñêà äî÷åðíèõ óçëîâ
procedure AppendChild(const aChild: IXmlNode);
// InsertBefore - äîáàâëÿåò óêàçàííûé óçåë â óêàçàííîå ìåñòî ñïèñêà äî÷åðíèõ óçëîâ
procedure InsertBefore(const aChild, aBefore: IXmlNode);
// ReplaceChild - çàìåíÿåò óêàçàííûé óçåë äðóãèì óçëîì
procedure ReplaceChild(const aNewChild, anOldChild: IXmlNode);
// RemoveChild - óäàëÿåò óêàçàííûé óçåë èç ñïèñêà äî÷åðíèõ óçëîâ
procedure RemoveChild(const aChild: IXmlNode);
// AppendElement - ñîçäàåò ýëåìåíò è äîáàâëÿåò åãî â êîíåö ñïèñêà
// â êîíåö ñïèñêà äî÷åðíèõ îáúåêòîâ
function AppendElement(aNameID: Integer): IXmlElement; overload;
function AppendElement(const aName: String): IXmlElement; overload;
// AppendText - ñîçäàåò òåêñòîâûé óçåë è äîáàâëÿåò åãî
// â êîíåö ñïèñêà äî÷åðíèõ îáúåêòîâ
function AppendText(const aData: String): IXmlText;
// AppendCDATA - ñîçäàåò ñåêöèþ CDATA è äîáàâëÿåò åå
// â êîíåö ñïèñêà äî÷åðíèõ îáúåêòîâ
function AppendCDATA(const aData: String): IXmlCDATASection;
// AppendComment - ñîçäàåò êîììåíòàðèé è äîáàâëÿåò åãî
// â êîíåö ñïèñêà äî÷åðíèõ îáúåêòîâ
function AppendComment(const aData: String): IXmlComment;
// AppendProcessingInstruction - ñîçäàåò èíñòðóêöèþ è äîáàâëÿåò å¸
// â êîíåö ñïèñêà äî÷åðíèõ îáúåêòîâ
function AppendProcessingInstruction(aTargetID: Integer;
const aData: String): IXmlProcessingInstruction; overload;
function AppendProcessingInstruction(const aTarget: String;
const aData: String): IXmlProcessingInstruction; overload;
// GetChildText - âîçâðàùàåò çíà÷åíèå äî÷åðíåãî óçëà
// SetChildText - äîáàâëÿåò èëè èçìåíÿåò çíà÷åíèå äî÷åðíåãî óçëà
function GetChildText(const aName: String; const aDefault: String = ''): String; overload;
function GetChildText(aNameID: Integer; const aDefault: String = ''): String; overload;
procedure SetChildText(const aName, aValue: String); overload;
procedure SetChildText(aNameID: Integer; const aValue: String); overload;
// NeedChild - âîçâðàùàåò äî÷åðíèé óçåë ñ óêàçàííûì èìåíåì.
// Åñëè óçåë íå íàéäåí, òî ãåíåðèðóåòñÿ èñêëþ÷åíèå
function NeedChild(aNameID: Integer): IXmlNode; overload;
function NeedChild(const aName: String): IXmlNode; overload;
// EnsureChild - âîçâðàùàåò äî÷åðíèé óçåë ñ óêàçàííûì èìåíåì.
// Åñëè óçåë íå íàéäåí, òî îí áóäåò ñîçäàí
function EnsureChild(aNameID: Integer): IXmlNode; overload;
function EnsureChild(const aName: String): IXmlNode; overload;
// RemoveAllChilds - óäàëÿåò âñå äî÷åðíèå óçëû
procedure RemoveAllChilds;
// SelectNodes - ïðîèçâîäèò âûáîðêó óçëîâ, óäîâëåòâîðÿþùèõ
// óêàçàííûì êðèòåðèÿì
function SelectNodes(const anExpression: String): IXmlNodeList; overload;
function SelectNodes(aNodeNameID: Integer): IXmlNodeList; overload;
// SelectSingleNode - ïðîèçâîäèò ïîèñê ïåðâîãî óçëà, óäîâëåòâîðÿþùåãî
// óêàçàííûì êðèòåðèÿì
function SelectSingleNode(const anExpression: String): IXmlNode;
// FindElement - ïðîèçâîäèò ïîèñê ïåðâîãî óçëà, óäîâëåòâîðÿþùåãî
// óêàçàííûì êðèòåðèÿì
function FindElement(const anElementName, anAttrName: String; const anAttrValue: Variant): IXmlElement;
function FindElements(const anElementName, anAttrName: String; const anAttrValue: Variant): IXmlNodeList;
// Get_AttrCount - âîçâðàùàåò êîëè÷åñòâî àòðèáóòîâ
function Get_AttrCount: Integer;
// Get_AttrNameID - âîçâðàùàåò êîä íàçâàíèÿ àòðèáóòà
function Get_AttrNameID(anIndex: Integer): Integer;
// Get_AttrName - âîçâðàùàåò íàçâàíèå àòðèáóòà
function Get_AttrName(anIndex: Integer): String;
// RemoveAttr - óäàëÿåò àòðèáóò
procedure RemoveAttr(const aName: String); overload;
procedure RemoveAttr(aNameID: Integer); overload;
// RemoveAllAttrs - óäàëÿåò âñå àòðèáóòû
procedure RemoveAllAttrs;
// AttrExists - ïðîâåðÿåò, çàäàí ëè óêàçàííûé àòðèáóò.
function AttrExists(aNameID: Integer): Boolean; overload;
function AttrExists(const aName: String): Boolean; overload;
// GetAttrType - âîçàðàùàåò òèï äàííûõ àòðèáóòà â òåðìèíàõ âàðèàíòîâ
function GetAttrType(aNameID: Integer): Integer; overload;
function GetAttrType(const aName: String): Integer; overload;
// GetAttrType - âîçâðàùàåò òèï àòðèáóòà
// Result
// GetVarAttr - âîçâðàùàåò òèïèçèðîâàííîå çíà÷åíèå óêàçàííîãî àòðèáóòà.
// Åñëè àòðèáóò íå çàäàí, òî âîçâðàùàåòñÿ çíà÷åíèå ïî óìîë÷àíèþ
// SetAttr - èçìåíÿåò èëè äîáàâëÿåò óêàçàííûé àòðèáóò
function GetVarAttr(aNameID: Integer; const aDefault: Variant): Variant; overload;
function GetVarAttr(const aName: String; const aDefault: Variant): Variant; overload;
procedure SetVarAttr(aNameID: Integer; const aValue: Variant); overload;
procedure SetVarAttr(const aName: String; aValue: Variant); overload;
function NeedVarAttr(aNameID: Integer): Variant; overload;
function NeedVarAttr(const aName: String): Variant; overload;
// NeedAttr - âîçâðàùàåò ñòðîêîâîå çíà÷åíèå óêàçàííîãî àòðèáóòà.
// Åñëè àòðèáóò íå çàäàí, òî ãåíåðèðóåòñÿ èñêëþ÷åíèå
function NeedAttr(aNameID: Integer): String; overload;
function NeedAttr(const aName: String): String; overload;
// GetAttr - âîçâðàùàåò ñòðîêîâîå çíà÷åíèå óêàçàííîãî àòðèáóòà.
// Åñëè àòðèáóò íå çàäàí, òî âîçâðàùàåòñÿ çíà÷åíèå ïî óìîë÷àíèþ
// SetAttr - èçìåíÿåò èëè äîáàâëÿåò óêàçàííûé àòðèáóò
function GetAttr(aNameID: Integer; const aDefault: String = ''): String; overload;
function GetAttr(const aName: String; const aDefault: String = ''): String; overload;
procedure SetAttr(aNameID: Integer; const aValue: String); overload;
procedure SetAttr(const aName, aValue: String); overload;
// GetBoolAttr - âîçâðàùàåò öåëî÷èñëåííîå çíà÷åíèå óêàçàííîãî àòðèáóòà
// SetBoolAttr - èçìåíÿåò èëè äîáàâëÿåò óêàçàííûé àòðèáóò öåëî÷èñëåííûì
// çíà÷åíèåì
function GetBoolAttr(aNameID: Integer; aDefault: Boolean = False): Boolean; overload;
function GetBoolAttr(const aName: String; aDefault: Boolean = False): Boolean; overload;
procedure SetBoolAttr(aNameID: Integer; aValue: Boolean = False); overload;
procedure SetBoolAttr(const aName: String; aValue: Boolean); overload;
// GetIntAttr - âîçâðàùàåò öåëî÷èñëåííîå çíà÷åíèå óêàçàííîãî àòðèáóòà
// SetIntAttr - èçìåíÿåò èëè äîáàâëÿåò óêàçàííûé àòðèáóò öåëî÷èñëåííûì
// çíà÷åíèåì
function GetIntAttr(aNameID: Integer; aDefault: Integer = 0): Integer; overload;
function GetIntAttr(const aName: String; aDefault: Integer = 0): Integer; overload;
function NeedIntAttr(const aName: String): Integer; overload;
function NeedIntAttr(aNameID: Integer): Integer; overload;
procedure SetIntAttr(aNameID: Integer; aValue: Integer); overload;
procedure SetIntAttr(const aName: String; aValue: Integer); overload;
// GetDateTimeAttr - âîçâðàùàåò öåëî÷èñëåííîå çíà÷åíèå óêàçàííîãî àòðèáóòà
// SetDateTimeAttr - èçìåíÿåò èëè äîáàâëÿåò óêàçàííûé àòðèáóò öåëî÷èñëåííûì
// çíà÷åíèåì
function GetDateTimeAttr(aNameID: Integer; aDefault: TDateTime = 0): TDateTime; overload;
function GetDateTimeAttr(const aName: String; aDefault: TDateTime = 0): TDateTime; overload;
procedure SetDateTimeAttr(aNameID: Integer; aValue: TDateTime); overload;
procedure SetDateTimeAttr(const aName: String; aValue: TDateTime); overload;
// GetFloatAttr - âîçâðàùàåò çíà÷åíèå óêàçàííîãî àòðèáóòà â âèäå
// âåùåñòâåííîãî ÷èñëà
// SetFloatAttr - èçìåíÿåò èëè äîáàâëÿåò óêàçàííûé àòðèáóò âåùåñòâåííûì
// çíà÷åíèåì
function GetFloatAttr(aNameID: Integer; aDefault: Double = 0): Double; overload;
function GetFloatAttr(const aName: String; aDefault: Double = 0): Double; overload;
function NeedFloatAttr(aNameID: Integer): Double; overload;
function NeedFloatAttr(const aName: String): Double; overload;
procedure SetFloatAttr(aNameID: Integer; aValue: Double); overload;
procedure SetFloatAttr(const aName: String; aValue: Double); overload;
// GetHexAttr - ïîëó÷åíèå çíà÷åíèÿ óêàçàííîãî àòðèáóòà â öåëî÷èñëåííîì âèäå.
// Ñòðîêîâîå çíà÷åíèå àòðèáóòà ïðåîáðàçóåòñÿ â öåëîå ÷èñëî. Èñõîäíàÿ
// ñòðîêà äîëæíà áûòü çàäàíà â øåñòíàäöàòèðè÷íîì âèäå áåç ïðåôèêñîâ
// ("$", "0x" è ïð.) Åñëè ïðåîáðàçîâàíèå íå ìîæåò áûòü âûïîëíåíî,
// ãåíåðèðóåòñÿ èñêëþ÷åíèå.
// Åñëè àòðèáóò íå çàäàí, âîçâðàùàåòñÿ çíà÷åíèå ïàðàìåòðà aDefault.
// SetHexAttr - èçìåíåíèå çíà÷åíèÿ óêàçàííîãî àòðèáóòà íà ñòðîêîâîå
// ïðåäñòàâëåíèå öåëîãî ÷èñëà â øåñòíàäöàòèðè÷íîì âèäå áåç ïðåôèêñîâ
// ("$", "0x" è ïð.) Åñëè ïðåîáðàçîâàíèå íå ìîæåò áûòü âûïîëíåíî,
// ãåíåðèðóåòñÿ èñêëþ÷åíèå.
// Åñëè àòðèáóò íå áûë çàäàí, äî îí áóäåò äîáàâëåí.
// Åñëè áûë çàäàí, òî áóäåò èçìåíåí.
function GetHexAttr(const aName: String; aDefault: Integer = 0): Integer; overload;
function GetHexAttr(aNameID: Integer; aDefault: Integer = 0): Integer; overload;
procedure SetHexAttr(const aName: String; aValue: Integer; aDigits: Integer = 8); overload;
procedure SetHexAttr(aNameID: Integer; aValue: Integer; aDigits: Integer = 8); overload;
// GetEnumAttr - èùåò çíà÷åíèå àòðèáóòà â óêàçàííîì ñïèñêå ñòðîê è
// âîçâðàùàåò èíäåêñ íàéäåííîé ñòðîêè. Åñëè àòðèáóò çàäàí íî íå íàéäåí
// â ñïèñêå, òî ãåíåðèðóåòñÿ èñêëþ÷åíèå.
// Åñëè àòðèáóò íå çàäàí, âîçâðàùàåòñÿ çíà÷åíèå ïàðàìåòðà aDefault.
function GetEnumAttr(const aName: String;
const aValues: array of String; aDefault: Integer = 0): Integer; overload;
function GetEnumAttr(aNameID: Integer;
const aValues: array of String; aDefault: Integer = 0): Integer; overload;
function NeedEnumAttr(const aName: String;
const aValues: array of String): Integer; overload;
function NeedEnumAttr(aNameID: Integer;
const aValues: array of String): Integer; overload;
// ReplaceTextByCDATASection - óäàëÿåò âñå òåêñòîâûå ýëåìåíòû è äîáàâëÿåò
// îäíó ñåêöèþ CDATA, ñîäåðæàùóþ óêàçàííûé òåêñò
procedure ReplaceTextByCDATASection(const aText: String);
// ReplaceTextByBinaryData - óäàëÿåò âñå òåêñòîâûå ýëåìåíòû è äîáàâëÿåò
// îäèí òåêñòîâûé ýëåìåíò, ñîäåðæàùèé óêàçàííûå äâîè÷íûå äàííûå
// â ôîðìàòå "base64".
// Åñëè ïàðàìåòð aMaxLineLength íå ðàâåí íóëþ, òî ïðîèçâîäèòñÿ ðàçáèâêà
// ïîëó÷åíîé ñòðîêè íà ñòðîêè äëèíîé aMaxLineLength.
// Ñòðîêè ðàçäåëÿþòñÿ ïàðîé ñèìâîëîâ #13#10 (CR,LF).
// Ïîñëå ïîñëåäíåé ñòðîêè óêàçàííûå ñèìâîëû íå âñòàâëÿþòñÿ.
procedure ReplaceTextByBinaryData(const aData; aSize: Integer;
aMaxLineLength: Integer);
// GetTextAsBinaryData - cîáèðàåò âñå òåêñòîâûå ýëåìåíòû â îäíó ñòðîêó è
// ïðîèçâîäèò ïðåîáðàçîâàíèå èç ôîðìàòà "base64" â äâîè÷íûå äàííûå.
// Ïðè ïðåîáðàçîâàíèè èãíîðèðóþòñÿ âñå ïðîáåëüíûå ñèìâîëû (ñ êîäîì <= ' '),
// ñîäåðæàùèåñÿ â èñõîäíîé ñòðîêå.
function GetTextAsBinaryData: RawByteString;
function GetOwnText: String;
function Get_Values(const aName: String): Variant;
procedure Set_Values(const aName: String; const aValue: Variant);
function AsElement: IXmlElement;
function AsText: IXmlText;
function AsCDATASection: IXmlCDATASection;
function AsComment: IXmlComment;
function AsProcessingInstruction: IXmlProcessingInstruction;
property SourceLine: Integer read Get_SourceLine;
property SourceCol: Integer read Get_SourceCol;
property NodeName: String read Get_NodeName;
property NodeNameID: Integer read Get_NodeNameID;
property NodeType: Integer read Get_NodeType;
property ParentNode: IXmlNode read Get_ParentNode;
property OwnerDocument: IXmlDocument read Get_OwnerDocument;
property NextSibling: IXmlNode read Get_NextSibling;
property NameTable: IXmlNameTable read Get_NameTable;
property ChildNodes: IXmlNodeList read Get_ChildNodes;
property AttrCount: Integer read Get_AttrCount;
property AttrNames[anIndex: Integer]: String read Get_AttrName;
property AttrNameIDs[anIndex: Integer]: Integer read Get_AttrNameID;
property Text: String read Get_Text write Set_Text;
property DataType: Integer read Get_DataType;
property TypedValue: Variant read Get_TypedValue write Set_TypedValue;
property Xml: String read Get_Xml;
property Values[const aName: String]: Variant read Get_Values write Set_Values; default;
end;
IXmlElement = interface(IXmlNode)
end;
IXmlCharacterData = interface(IXmlNode)
end;
IXmlText = interface(IXmlCharacterData)
end;
IXmlCDATASection = interface(IXmlCharacterData)
end;
IXmlComment = interface(IXmlCharacterData)
end;
IXmlProcessingInstruction = interface(IXmlNode)
function Get_Target: String;
property Target: String read Get_Target;
end;
IXmlDocument = interface(IXmlNode)
function Get_DocumentElement: IXmlElement;
function Get_BinaryXML: RawByteString;
function Get_PreserveWhiteSpace: Boolean;
procedure Set_PreserveWhiteSpace(aValue: Boolean);
function NewDocument(const aVersion, anEncoding: String;
aRootElementNameID: Integer): IXmlElement; overload;
function NewDocument(const aVersion, anEncoding,
aRootElementName: String): IXmlElement; overload;
function CreateElement(aNameID: Integer): IXmlElement; overload;
function CreateElement(const aName: String): IXmlElement; overload;
function CreateText(const aData: String): IXmlText;
function CreateCDATASection(const aData: String): IXmlCDATASection;
function CreateComment(const aData: String): IXmlComment;
function CreateProcessingInstruction(const aTarget,
aData: String): IXmlProcessingInstruction; overload;
function CreateProcessingInstruction(aTargetID: Integer;
const aData: String): IXmlProcessingInstruction; overload;
procedure LoadXML(const anXml: String); overload;
{$if CompilerVersion >= 20}
procedure LoadXML(const anXml: RawByteString); overload;
{$ifend}
procedure LoadBinaryXML(const anXml: RawByteString);
procedure Load(aStream: TStream); overload;
procedure Load(const aFileName: String); overload;
procedure LoadResource(aType, aName: PChar);
procedure Save(aStream: TStream); overload;
procedure Save(const aFileName: String); overload;
procedure SaveBinary(aStream: TStream; anOptions: LongWord = 0); overload;
procedure SaveBinary(const aFileName: String; anOptions: LongWord = 0); overload;
property PreserveWhiteSpace: Boolean read Get_PreserveWhiteSpace write Set_PreserveWhiteSpace;
property DocumentElement: IXmlElement read Get_DocumentElement;
property BinaryXML: RawByteString read Get_BinaryXML;
end;
function CreateNameTable(aHashTableSize: Integer = 4096): IXmlNameTable;
function CreateXmlDocument(
const aRootElementName: String = '';
const aVersion: String = '1.0';
const anEncoding: String = ''; // SimpleXmlDefaultEncoding
const aNames: IXmlNameTable = nil): IXmlDocument;
function CreateXmlElement(const aName: String; const aNameTable: IXmlNameTable = nil): IXmlElement;
function CreateXmlNodeList: IXmlNodeList;
function LoadXmlDocumentFromXml(const anXml: String): IXmlDocument;
function LoadXmlDocumentFromBinaryXML(const aBinaryXml: RawByteString): IXmlDocument;
function LoadXmlDocument(aStream: TStream): IXmlDocument; overload;
function LoadXmlDocument(const aFileName: String): IXmlDocument; overload;
function LoadXmlDocument(aResType, aResName: PChar): IXmlDocument; overload;
var
DefaultNameTable: IXmlNameTable = nil;
DefaultPreserveWhiteSpace: Boolean = False;
DefaultEncoding: String = 'windows-1251';
DefaultIndentText: String = ^I;
resourcestring
SSimpleXmlError1 = 'Îøèáêà ïîëó÷åíèÿ ýëåìåíòà ñïèñêà: èíäåêñ âûõîäèò çà ïðåäåëû';
SSimpleXmlError2 = 'Íå çàâåðøåíî îïðåäåëåíèå ýëåìåíòà';
SSimpleXmlError3 = 'Íåêîððåòíûé ñèìâîë â èìåíè ýëåìåíòà';
SSimpleXmlError4 = 'Îøèáêà ÷òåíèÿ äâîè÷íîãî XML: íåêîððåêòíûé òèï óçëà';
SSimpleXmlError5 = 'Îøèáêà çàïèñè äâîè÷íîãî XML: íåêîððåêòíûé òèï óçëà';
SSimpleXmlError6 = 'Íåâåðíîå çíà÷åíèå àòðèáóòà "%s" ýëåìåíòà "%s".'^M^J +
'Äîïóñòèìûå çíà÷åíèÿ:'^M^J +
'%s';
SSimpleXmlError7 = 'Íå íàéäåí àòðèáóò "%s"';
SSimpleXmlError8 = 'Íå çàäàí àòðèáóò "%s"';
SSimpleXmlError9 = 'Äàííàÿ âîçìîæíîñòü íå ïîääåðæèâàåòñÿ SimpleXML';
SSimpleXmlError10 = 'Îøèáêà: íå íàéäåí äî÷åðíèé ýëåìåíò "%s".';
SSimpleXmlError11 = 'Èìÿ äîëæíî íà÷èíàòüñÿ ñ áóêâû èëè "_" (ñòð. %d, ïîç. %d)';
SSimpleXmlError12 = 'Îæèäàåòñÿ ÷èñëî (ñòð. %d, ïîç. %d)';
SSimpleXmlError13 = 'Îæèäàåòñÿ øåñòíàäöàòåðè÷íîå ÷èñëî (ñòð. %d, ïîç. %d)';
SSimpleXmlError14 = 'Îæèäàåòñÿ "#" èëè èìÿ óïðàìëÿþùåãî ñèìâîëà (ñòð. %d, ïîç. %d)';
SSimpleXmlError15 = 'Íåêîððåêòíîå èìÿ óïðàâëÿþùåãî ñèìâîëà (ñòð. %d, ïîç. %d)';
SSimpleXmlError16 = 'Îæèäàåòñÿ "%s" (ñòð. %d, ïîç. %d)';
SSimpleXmlError17 = 'Îæèäàåòñÿ "%s" (ñòð. %d, ïîç. %d)';
SSimpleXmlError18 = 'Ñèìâîë "<" íå ìîæåò èñïîëüçîâàòüñÿ â çíà÷åíèÿõ àòðèáóòîâ (ñòð. %d, ïîç. %d)';
SimpleXmlError19 = 'Îæèäàåòñÿ "%s" (ñòð. %d, ïîç. %d)';
SSimpleXmlError20 = 'Îæèäàåòñÿ çíà÷åíèå àòðèáóòà (ñòð. %d, ïîç. %d)';
SSimpleXmlError21 = 'Îæèäàåòñÿ ñòðîêîâàÿ êîíñòàíòà (ñòð. %d, ïîç. %d)';
SimpleXmlError22 = 'Îæèäàåòñÿ "%s" (ñòð. %d, ïîç. %d)';
SSimpleXmlError23 = 'Îøèáêà ÷òåíèÿ äàííûõ.';
SSimpleXmlError24 = 'Îøèáêà ÷òåíèÿ çíà÷åíèÿ: íåêîððåêòíûé òèï.';
SSimpleXmlError25 = 'Îøèáêà çàïèñè çíà÷åíèÿ: íåêîððåêòíûé òèï.';
SSimpleXmlError26 = '%s (ôàéë: "%s")';
SSimpleXmlError27 = 'Îøèáêà óñòàíîâêè çíà÷åíèÿ àòðèáóòà: íå çàäàíî èìÿ.';
function XSTRToFloat(s: String): Double;
function FloatToXSTR(v: Double): String;
function DateTimeToXSTR(v: TDateTime): String;
function VarToXSTR(const v: TVarData): String;
function TextToXML(const aText: String): String;
function BinToBase64(const aBin; aSize, aMaxLineLength: Integer): String;
function Base64ToBin(const aBase64: String): RawByteString;
function IsXmlDataString(const aData: RawByteString): Boolean;
function XmlIsInBinaryFormat(const aData: RawByteString): Boolean;
function AppendChildNodeFromXml(const aParentNode: IXmlNode; const anXml: String): IXmlNode;
implementation
uses
Variants, DateUtils;
const
BinXmlSignatureSize = Length('< binary-xml >');
BinXmlSignature: RawByteString = '< binary-xml >';
type
TStringBuilder = object
private
FData: String;
FLength: Integer;
public
procedure Init;
procedure Add(const s: String);
procedure GetString(var aString: String);
end;
{ TStringBuilder }
procedure TStringBuilder.Init;
begin
FData := '';
FLength := 0;
end;
procedure TStringBuilder.Add(const s: String);
var
anAddLength,
aNewLength: Integer;
begin
anAddLength := Length(s);
if anAddLength = 0 then begin
Exit;
end;
aNewLength := FLength + anAddLength;
if aNewLength > Length(FData) then begin
if aNewLength > 64 then begin
SetLength(FData, aNewLength + aNewLength div 4)
end
else if aNewLength > 8 then begin
SetLength(FData, aNewLength + 16)
end
else begin
SetLength(FData, aNewLength + 4);
end
end;
Move(s[1], FData[FLength + 1], anAddLength*sizeof(Char));
FLength := aNewLength;
end;
procedure TStringBuilder.GetString(var aString: String);
begin
aString := Copy(FData, 1, FLength);
end;
procedure CopyChars(const aFrom: String; var aTo: String; var aPos: Integer);
begin
Move(aFrom[1], aTo[aPos], Length(aFrom)*sizeof(Char));
Inc(aPos, Length(aFrom));
end;
function TextToXML(const aText: String): String;
var
i, j: Integer;
begin
j := 0;
for i := 1 to Length(aText) do begin
case aText[i] of
'<', '>': Inc(j, 4);
'&': Inc(j, 5);
'"': Inc(j, 6);
else begin
Inc(j);
end
end;
end;
if j = Length(aText) then begin
Result := aText
end
else begin
SetLength(Result, j);
j := 1;
for i := 1 to Length(aText) do begin
case aText[i] of
'<': begin CopyChars('<', Result, j) end;
'>': begin CopyChars('>', Result, j) end;
'&': begin CopyChars('&', Result, j) end;
'"': begin CopyChars('"', Result, j) end;
else begin Result[j] := aText[i]; Inc(j) end;
end;
end;
end;
end;
function XSTRToFloat(s: String): Double;
var
aPos: Integer;
fmt : TFormatSettings;
begin
GetLocaleFormatSettings(LOCALE_SYSTEM_DEFAULT, fmt);
if '.' = fmt.DecimalSeparator then begin
aPos := Pos(',', s)
end
else if ',' = fmt.DecimalSeparator then begin
aPos := Pos('.', s)
end
else begin
aPos := Pos(',', s);
if aPos = 0 then begin
aPos := Pos('.', s);
end
end;
if aPos <> 0 then begin
s[aPos] := fmt.DecimalSeparator;
end;
Result := StrToFloat(s);
end;
function FloatToXSTR(v: Double): String;
var
aPos: Integer;
fmt : TFormatSettings;
begin
Result := FloatToStr(v);
GetLocaleFormatSettings(LOCALE_SYSTEM_DEFAULT, fmt);
aPos := Pos(fmt.DecimalSeparator, Result);
if aPos <> 0 then begin
Result[aPos] := '.';
end;
end;
function IsDigit(c: Char): Boolean;
begin
Result := (c >= '0') and (c <= '9')
end;
function XSTRToDateTime(const s: String): TDateTime;
var
aPos: Integer;
function FetchTo(aStop: Char): Integer;
var
i: Integer;
begin
i := aPos;
while (i <= Length(s)) and IsDigit(s[i]) do begin
Inc(i);
end;
if i > aPos then
Result := StrToInt(Copy(s, aPos, i - aPos))
else
Result := 0;
if (i <= Length(s)) and (s[i] = aStop) then
aPos := i + 1
else
aPos := Length(s) + 1;
end;
var
y, m, d, h, n, ss: Integer;
begin
aPos := 1;
y := FetchTo('-'); m := FetchTo('-'); d := FetchTo('T');
h := FetchTo('-'); n := FetchTo('-'); ss := FetchTo('-');
Result := EncodeDateTime(y, m, d, h, n, ss, 0);
end;
function DateTimeToXSTR(v: TDateTime): String;
var
y, m, d, h, n, s, ms: Word;
begin
DecodeDateTime(v, y, m, d, h, n, s, ms);
Result := Format('%.4d-%.2d-%.2dT%.2d:%.2d:%.2d', [y, m, d, h, n, s])
end;
function VarToXSTR(const v: TVarData): String;
const
BoolStr: array[Boolean] of String = ('0', '1');
var
p: Pointer;
begin
case v.VType of
varNull: Result := XSTR_NULL;
varSmallint: Result := IntToStr(v.VSmallInt);
varInteger: Result := IntToStr(v.VInteger);
varSingle: Result := FloatToXSTR(v.VSingle);
varDouble: Result := FloatToXSTR(v.VDouble);
varCurrency: Result := FloatToXSTR(v.VCurrency);
varDate: Result := DateTimeToXSTR(v.VDate);
varOleStr: Result := v.VOleStr;
varBoolean: Result := BoolStr[v.VBoolean = True];
varShortInt: Result := IntToStr(v.VShortInt);
varByte: Result := IntToStr(v.VByte);
varWord: Result := IntToStr(v.VWord);
varLongWord: Result := IntToStr(v.VLongWord);
varInt64: Result := IntToStr(v.VInt64);
varString: Result := String(AnsiString(v.VString));
{$if CompilerVersion >= 20}
varUString: Result := String(v.VString);
{$ifend}
varArray + varByte: begin
p := VarArrayLock(Variant(v));
try
Result := BinToBase64(p^, VarArrayHighBound(Variant(v), 1) - VarArrayLowBound(Variant(v), 1) + 1, 0);
finally
VarArrayUnlock(Variant(v))
end
end;
else begin
Result := Variant(v)
end
end;
end;
function LoadXMLResource(aModule: HMODULE; aName, aType: PChar; const aXMLDoc: IXmlDocument): boolean;
var
aRSRC: HRSRC;
aGlobal: HGLOBAL;
aSize: DWORD;
aPointer: Pointer;
aStream: TStringStream;
begin
Result := false;
aRSRC := FindResource(aModule, aName, aType);
if aRSRC <> 0 then begin
aGlobal := LoadResource(aModule, aRSRC);
aSize := SizeofResource(aModule, aRSRC);
if (aGlobal <> 0) and (aSize <> 0) then begin
aPointer := LockResource(aGlobal);
if Assigned(aPointer) then begin
aStream := TStringStream.Create('');
try
aStream.WriteBuffer(aPointer^, aSize);
aXMLDoc.LoadXML(aStream.DataString);
Result := true;
finally
aStream.Free;
end;
end;
end;
end;
end;
function IsWhitespace(c: Char): Boolean;
begin
Result := c <= ' ';
end;
function IsAnsiWhitespace(c: AnsiChar): Boolean;
begin
Result := c <= ' ';
end;
function IsXmlDataString(const aData: RawByteString): Boolean;
var
i: Integer;
begin
Result := Copy(aData, 1, BinXmlSignatureSize) = BinXmlSignature;
if not Result then begin
i := 1;
while (i <= Length(aData)) and IsAnsiWhitespace(aData[i]) do begin
Inc(i);
end;
Result := Copy(aData, i, Length('<?xml ')) = '<?xml ';
end;
end;
function XmlIsInBinaryFormat(const aData: RawByteString): Boolean;
begin
Result := Copy(aData, 1, BinXmlSignatureSize) = BinXmlSignature
end;
var
Base64Map: array [0..63] of Char = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
type
PChars = ^TChars;
TChars = packed record a, b, c, d: Char end;
POctet = ^TOctet;
TOctet = packed record a, b, c: Byte; end;
procedure OctetToChars(po: POctet; aCount: Integer; pc: PChars);
var
o: Integer;
begin
if aCount = 1 then begin
o := po.a shl 16;
pc.a := Base64Map[(o shr 18) and $3F];
pc.b := Base64Map[(o shr 12) and $3F];
pc.c := '=';
pc.d := '=';
end
else if aCount = 2 then begin
o := po.a shl 16 or po.b shl 8;
pc.a := Base64Map[(o shr 18) and $3F];
pc.b := Base64Map[(o shr 12) and $3F];
pc.c := Base64Map[(o shr 6) and $3F];
pc.d := '=';
end
else if aCount > 2 then begin
o := po.a shl 16 or po.b shl 8 or po.c;
pc.a := Base64Map[(o shr 18) and $3F];
pc.b := Base64Map[(o shr 12) and $3F];
pc.c := Base64Map[(o shr 6) and $3F];
pc.d := Base64Map[o and $3F];
end;
end;
function BinToBase64(const aBin; aSize, aMaxLineLength: Integer): String;
var
o: POctet;
c: PChars;
aCount: Integer;
i: Integer;
begin
o := @aBin;
aCount := aSize;
SetLength(Result, ((aCount + 2) div 3)*4);
c := PChars(Result);
while aCount > 0 do begin
OctetToChars(o, aCount, c);
Inc(o);
Inc(c);
Dec(aCount, 3);
end;
if aMaxLineLength > 0 then begin
i := aMaxLineLength;
while i <= Length(Result) do begin
Insert(#13#10, Result, i);
Inc(i, 2 + aMaxLineLength);
end
end;
end;
function CharTo6Bit(c: Char): Byte;
begin
if (c >= 'A') and (c <= 'Z') then begin
Result := Ord(c) - Ord('A')
end
else if (c >= 'a') and (c <= 'z') then begin
Result := Ord(c) - Ord('a') + 26
end
else if (c >= '0') and (c <= '9') then begin
Result := Ord(c) - Ord('0') + 52
end
else if c = '+' then begin
Result := 62
end
else if c = '/' then begin
Result := 63
end
else begin
Result := 0
end
end;
procedure CharsToOctet(c: PChars; o: POctet);
var
i: Integer;
begin
if c.c = '=' then begin // 1 byte
i := CharTo6Bit(c.a) shl 18 or CharTo6Bit(c.b) shl 12;
o.a := (i shr 16) and $FF;
end
else if c.d = '=' then begin // 2 bytes
i := CharTo6Bit(c.a) shl 18 or CharTo6Bit(c.b) shl 12 or CharTo6Bit(c.c) shl 6;
o.a := (i shr 16) and $FF;
o.b := (i shr 8) and $FF;
end
else begin // 3 bytes
i := CharTo6Bit(c.a) shl 18 or CharTo6Bit(c.b) shl 12 or CharTo6Bit(c.c) shl 6 or CharTo6Bit(c.d);
o.a := (i shr 16) and $FF;
o.b := (i shr 8) and $FF;
o.c := i and $FF;
end;
end;
function Base64ToBin(const aBase64: String): RawByteString;
var
o: POctet;
c: PChars;
aCount: Integer;
s: String;
i, j: Integer;
begin
s := aBase64;
i := 1;
while i <= Length(s) do begin
while (i <= Length(s)) and (s[i] > ' ') do begin
Inc(i);
end;
if i <= Length(s) then begin
j := i;
while (j <= Length(s)) and (s[j] <= ' ') do begin
Inc(j);
end;
Delete(s, i, j - i);
end;
end;
if Length(s) < 4 then begin
SetLength(Result, 0)
end
else begin
aCount := ((Length(s) + 3) div 4)*3;
if aCount > 0 then begin
if s[Length(s) - 1] = '=' then begin
Dec(aCount, 2)
end
else if s[Length(s)] = '=' then begin
Dec(aCount);
end;
SetLength(Result, aCount);
FillChar(Result[1], aCount, 0);
c := @s[1];
o := @Result[1];
while aCount > 0 do begin
CharsToOctet(c, o);
Inc(o);
Inc(c);
Dec(aCount, 3);
end;
end;
end;
end;
type
TBinaryXmlReader = class
private
FOptions: LongWord;
public
procedure Read(var aBuf; aSize: Integer); virtual; abstract;
function ReadLongint: Longint;
function ReadAnsiString: AnsiString;
function ReadUnicodeString: UnicodeString;
function ReadXmlString: String;
procedure ReadVariant(var v: TVarData);
end;
TStreamBinaryXmlReader = class(TBinaryXmlReader)
private
FStream: TStream;
FOptions: LongWord;
FBufStart,
FBufEnd,
FBufPtr: PByte;
FBufSize,
FRestSize: Integer;
public
constructor Create(aStream: TStream; aBufSize: Integer);
destructor Destroy; override;
procedure Read(var aBuf; aSize: Integer); override;
end;
TRawByteStringBinaryXmlReader = class(TBinaryXmlReader)
private
FString: RawByteString;
FOptions: LongWord;
FPtr: PByte;
FRestSize: Integer;
public
constructor Create(const aStr: RawByteString);
procedure Read(var aBuf; aSize: Integer); override;
end;
TBinaryXmlWriter = class
private
FOptions: LongWord;
public
procedure Write(const aBuf; aSize: Integer); virtual; abstract;
procedure WriteLongint(aValue: Longint);
procedure WriteAnsiString(const aValue: AnsiString);
procedure WriteUnicodeString(const aValue: UnicodeString);
procedure WriteXmlString(const aValue: String);
procedure WriteVariant(const v: TVarData);
end;
TStreamBinrayXmlWriter = class(TBinaryXmlWriter)