-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathNativeXml.pas
More file actions
6405 lines (5828 loc) · 203 KB
/
NativeXml.pas
File metadata and controls
6405 lines (5828 loc) · 203 KB
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 NativeXml
This is a small-footprint implementation to read and write XML documents
natively from Delpi code.
You can use this code to read XML documents from files, streams or strings.
The load routine generates events that can be used to display load progress
on the fly.
Note: any external encoding (ANSI, UTF16, etc) is converted to an internal
encoding that is ANSI or UTF8. When the loaded document is ANSI based,
the encoding will be ANSI, in other cases (UTF8, UTF16) the encoding
will be UTF8.
Original Author: Nils Haeck M.Sc. (n.haeck@simdesign.nl)
Original Date: 01 Apr 2003
Version: see below
Copyright (c) 2003-2009 Simdesign BV
It is NOT allowed under ANY circumstances to publish or copy this code
without accepting the license conditions in accompanying LICENSE.txt
first!
This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
ANY KIND, either express or implied.
Please visit http://www.simdesign.nl/xml.html for more information.
}
{$DEFINE USEGRAPHICS} // uncomment if you do not want to include the Graphics unit.
// Delphi and BCB versions
// Delphi 5
{$IFDEF VER130}
{$DEFINE D5UP}
{$ENDIF}
//Delphi 6
{$IFDEF VER140}
{$DEFINE D5UP}
{$DEFINE D6UP}
{$ENDIF}
//Delphi 7
{$IFDEF VER150}
{$DEFINE D5UP}
{$DEFINE D6UP}
{$DEFINE D7UP}
{$ENDIF}
//Delphi 8
{$IFDEF VER160}
{$DEFINE D5UP}
{$DEFINE D6UP}
{$DEFINE D7UP}
{$DEFINE D8UP}
{$ENDIF}
// Delphi 2005
{$IFDEF VER170}
{$DEFINE D5UP}
{$DEFINE D6UP}
{$DEFINE D7UP}
{$DEFINE D8UP}
{$DEFINE D9UP}
{$ENDIF}
// Delphi 2006
{$IFDEF VER180}
{$DEFINE D5UP}
{$DEFINE D6UP}
{$DEFINE D7UP}
{$DEFINE D8UP}
{$DEFINE D9UP}
{$DEFINE D10UP}
{$ENDIF}
// Delphi 2007 - NET
{$IFDEF VER190}
{$DEFINE D5UP}
{$DEFINE D6UP}
{$DEFINE D7UP}
{$DEFINE D8UP}
{$DEFINE D9UP}
{$DEFINE D10UP}
{$ENDIF}
// Delphi 2009
{$IFDEF VER200}
{$DEFINE D5UP}
{$DEFINE D6UP}
{$DEFINE D7UP}
{$DEFINE D8UP}
{$DEFINE D9UP}
{$DEFINE D10UP}
{$DEFINE D11UP}
{$DEFINE D12UP}
{$ENDIF}
// Delphi 2010
{$IFDEF VER210}
{$DEFINE D5UP}
{$DEFINE D6UP}
{$DEFINE D7UP}
{$DEFINE D8UP}
{$DEFINE D9UP}
{$DEFINE D10UP}
{$DEFINE D11UP}
{$DEFINE D12UP}
{$DEFINE D14UP}
{$ENDIF}
unit NativeXml;
interface
uses
{$IFDEF D9UP}
Windows,
{$ENDIF}
{$IFDEF CLR}
System.Text,
{$ENDIF}
{$IFDEF USEGRAPHICS}
{$IFDEF LINUX}
QGraphics,
{$ELSE}
Graphics,
{$ENDIF}
{$ENDIF}
Classes,
SysUtils;
const
// Current version of the NativeXml unit
cNativeXmlVersion = '3.06';
// cross-platform pointer type
type
{$IFDEF CLR}
TPointer = TObject;
{$ELSE}
TPointer = Pointer;
{$ENDIF}
// Delphi 5 stubs
{$IFNDEF D6UP}
type
TSeekOrigin = Word;
UTF8String = AnsiString;
const
soBeginning = soFromBeginning;
soCurrent = soFromCurrent;
soEnd = soFromEnd;
{$ENDIF}
{$IFNDEF D12UP}
// Delphi 2007 and below
type
UnicodeString = WideString;
UnicodeChar = WideChar;
PUnicodeChar = PWideChar;
RawByteString = AnsiString;
{$ELSE}
type
UnicodeChar = Char;
PUnicodeChar = PChar;
{$ENDIF}
type
// Note on TNativeXml.Format:
// - xfReadable (default) to be able to read the xml file with a standard editor.
// - xfCompact to save the xml fully compliant and at smallest size
TXmlFormatType = (
xfReadable, // Save in readable format with CR-LF and indents
xfCompact // Save without any control chars except LF after declarations
);
// TXmlElementType enumerates the different kinds of elements that can be found
// in the XML document.
TXmlElementType = (
xeNormal, // Normal element <name {attr}>[value][sub-elements]</name>
xeComment, // Comment <!--{comment}-->
xeCData, // literal data <![CDATA[{data}]]>
xeDeclaration, // XML declaration <?xml{declaration}?>
xeStylesheet, // Stylesheet <?xml-stylesheet{stylesheet}?>
xeDoctype, // DOCTYPE DTD declaration <!DOCTYPE{spec}>
xeElement, // <!ELEMENT >
xeAttList, // <!ATTLIST >
xeEntity, // <!ENTITY >
xeNotation, // <!NOTATION >
xeExclam, // Any <!data>
xeQuestion, // Any <?data?>
xeCharData, // character data in a node
xeUnknown // Any <data>
);
// Choose what kind of binary encoding will be used when calling
// TXmlNode BufferRead and BufferWrite.
TBinaryEncodingType = (
xbeBinHex, { With this encoding, each byte is stored as a hexadecimal
number, e.g. 0 = 00 and 255 = FF. }
xbeBase64 { With this encoding, each group of 3 bytes are stored as 4
characters, requiring 64 different AnsiCharacters.}
);
// Definition of different methods of String encoding.
TStringEncodingType = (
seAnsi, // General 8 bit encoding, encoding must be determined from encoding declaration
seUCS4BE, // UCS-4 Big Endian
seUCS4LE, // UCS-4 Little Endian
seUCS4_2143, // UCS-4 unusual octet order (2143)
seUCS4_3412, // UCS-4 unusual octet order (3412)
se16BitBE, // General 16 bit Big Endian, encoding must be determined from encoding declaration
se16BitLE, // General 16 bit Little Endian, encoding must be determined from encoding declaration
seUTF8, // UTF-8
seUTF16BE, // UTF-16 Big Endian
seUTF16LE, // UTF-16 Little Endian
seEBCDIC // EBCDIC flavour
);
TXmlCompareOption = (
xcNodeName,
xcNodeType,
xcNodeValue,
xcAttribCount,
xcAttribNames,
xcAttribValues,
xcChildCount,
xcChildNames,
xcChildValues,
xcRecursive
);
TXmlCompareOptions = set of TXmlCompareOption;
const
xcAll: TXmlCompareOptions = [xcNodeName, xcNodeType, xcNodeValue, xcAttribCount,
xcAttribNames, xcAttribValues, xcChildCount, xcChildNames, xcChildValues,
xcRecursive];
var
// XML Defaults
cDefaultEncodingString: UTF8String = 'UTF-8';
cDefaultExternalEncoding: TStringEncodingType = seUTF8;
cDefaultVersionString: UTF8String = '1.0';
cDefaultXmlFormat: TXmlFormatType = xfCompact;
cDefaultWriteOnDefault: boolean = True;
cDefaultBinaryEncoding: TBinaryEncodingType = xbeBase64;
cDefaultIndentString: UTF8String = ' ';
cDefaultDropCommentsOnParse: boolean = False;
cDefaultUseFullNodes: boolean = False;
cDefaultFloatAllowScientific: boolean = True;
cDefaultFloatSignificantDigits: integer = 6;
type
TXmlNode = class;
TNativeXml = class;
TsdCodecStream = class;
// An event that is based on the TXmlNode object Node.
TXmlNodeEvent = procedure(Sender: TObject; Node: TXmlNode) of object;
// An event that is used to indicate load or save progress.
TXmlProgressEvent = procedure(Sender: TObject; Size: integer) of object;
// This event is used in the TNativeXml.OnNodeCompare event, and should
// return -1 if Node1 < Node2, 0 if Node1 = Node2 and 1 if Node1 > Node2.
TXmlNodeCompareEvent = function(Sender: TObject; Node1, Node2: TXmlNode; Info: TPointer): integer of object;
// Pass a function of this kind to TXmlNode.SortChildNodes. The function should
// return -1 if Node1 < Node2, 0 if Node1 = Node2 and 1 if Node1 > Node2.
TXMLNodeCompareFunction = function(Node1, Node2: TXmlNode; Info: TPointer): integer;
// Very simple autonomous stringlist that holds the list of attributes in the node
TsdUTF8StringList = class(TPersistent)
private
FItems: array of UTF8String;
FCount: integer;
function GetItems(Index: integer): UTF8String;
procedure SetItems(Index: integer; const Value: UTF8String);
function GetValues(const Name: UTF8String): UTF8String;
function GetNames(Index: integer): UTF8String;
procedure SetValues(const Name, Value: UTF8String);
function GetText: UTF8String;
public
function Add(const S: UTF8String): integer;
procedure Assign(Source: TPersistent); override;
procedure Clear;
procedure Delete(Index: Integer);
function IndexOfName(const Name: UTF8String): integer;
property Count: integer read FCount;
property Items[Index: integer]: UTF8String read GetItems write SetItems; default;
property Names[Index: integer]: UTF8String read GetNames;
property Values[const Name: UTF8String]: UTF8String read GetValues write SetValues;
property Text: UTF8String read GetText;
end;
// The TXmlNode represents an element in the XML file. Each TNativeXml holds
// one Root element. Under ths root element, sub-elements can be nested (there
// is no limit on how deep). Property ElementType defines what kind of element
// this node is.
TXmlNode = class(TPersistent)
private
FName: UTF8String; // The element name
FValue: UTF8String; // The *escaped* value
FAttributes: TsdUTF8StringList; // List with attributes
FNodes: TList; // These are the child elements
FParent: TXmlNode; // Pointer to parent element
FDocument: TNativeXml; // Pointer to parent XmlDocument
FElementType: TXmlElementType; // The type of element
FTag: integer; // A value the developer can use
function AbortParsing: boolean;
function GetValueAsString: UTF8String;
procedure SetAttributeName(Index: integer; const Value: UTF8String);
procedure SetAttributeValue(Index: integer; const Value: UTF8String);
procedure SetValueAsString(const AValue: UTF8String);
function GetIndent: UTF8String;
function GetLineFeed: UTF8String;
function GetTreeDepth: integer;
function GetAttributeCount: integer;
function GetAttributePair(Index: integer): UTF8String;
function GetAttributeName(Index: integer): UTF8String;
function GetAttributeValue(Index: integer): UTF8String;
function GetWriteOnDefault: boolean;
function GetBinaryEncoding: TBinaryEncodingType;
function GetCascadedName: UTF8String;
function QualifyAsDirectNode: boolean;
procedure SetName(const Value: UTF8String);
function GetFullPath: UTF8String;
procedure SetBinaryEncoding(const Value: TBinaryEncodingType);
function GetBinaryString: RawByteString;
procedure SetBinaryString(const Value: RawByteString);
function UseFullNodes: boolean;
function GetValueAsUnicodeString: UnicodeString;
procedure SetValueAsUnicodeString(const Value: UnicodeString);
function GetAttributeByName(const AName: UTF8String): UTF8String;
procedure SetAttributeByName(const AName, Value: UTF8String);
function GetValueAsInteger: integer;
procedure SetValueAsInteger(const Value: integer);
function GetValueAsFloat: double;
procedure SetValueAsFloat(const Value: double);
function GetValueAsDateTime: TDateTime;
procedure SetValueAsDateTime(const Value: TDateTime);
function GetValueAsBool: boolean;
procedure SetValueAsBool(const Value: boolean);
function GetValueAsInt64: int64;
procedure SetValueAsInt64(const Value: int64);
procedure CheckCreateAttributesList;
function GetAttributeValueAsUnicodeString(Index: integer): UnicodeString;
procedure SetAttributeValueAsUnicodeString(Index: integer;
const Value: UnicodeString);
function GetAttributeValueAsInteger(Index: integer): integer;
procedure SetAttributeValueAsInteger(Index: integer;
const Value: integer);
function GetAttributeByNameWide(const AName: UTF8String): UnicodeString;
procedure SetAttributeByNameWide(const AName: UTF8String;
const Value: UnicodeString);
function GetTotalNodeCount: integer;
function FloatSignificantDigits: integer;
function FloatAllowScientific: boolean;
function GetAttributeValueDirect(Index: integer): UTF8String;
procedure SetAttributeValueDirect(Index: integer; const Value: UTF8String);
protected
function CompareNodeName(const NodeName: UTF8String): integer;
procedure DeleteEmptyAttributes;
function GetNodes(Index: integer): TXmlNode; virtual;
function GetNodeCount: integer; virtual;
procedure ParseTag(const AValue: UTF8String; TagStart, TagClose: integer);
procedure ReadFromStream(S: TStream); virtual;
procedure ReadFromString(const AValue: UTF8String); virtual;
procedure ResolveEntityReferences;
function UnescapeString(const AValue: UTF8String): UTF8String; virtual;
function WriteInnerTag: UTF8String; virtual;
procedure WriteToStream(S: TStream); virtual;
procedure ChangeDocument(ADocument: TNativeXml);
public
// Create a new TXmlNode object. ADocument must be the TNativeXml that is
// going to hold this new node.
constructor Create(ADocument: TNativeXml); virtual;
// \Create a new TXmlNode with name AName. ADocument must be the TNativeXml
// that is going to hold this new node.
constructor CreateName(ADocument: TNativeXml; const AName: UTF8String); virtual;
// \Create a new TXmlNode with name AName and UTF8String value AValue. ADocument
// must be the TNativeXml that is going to hold this new node.
constructor CreateNameValue(ADocument: TNativeXml; const AName, AValue: UTF8String); virtual;
// \Create a new TXmlNode with XML element type AType. ADocument must be the
// TNativeXml that is going to hold this new node.
constructor CreateType(ADocument: TNativeXml; AType: TXmlElementType); virtual;
// Use Assign to assign another TXmlNode to this node. This means that all
// properties and subnodes from the Source TXmlNode are copied to the current
// node. You can also Assign a TNativeXml document to the node, in that case
// the RootNodeList property of the TNativeXml object will be copied.
procedure Assign(Source: TPersistent); override;
// Call Delete to delete this node completely from the parent node list. This
// call only succeeds if the node has a parent. It has no effect when called for
// the root node.
procedure Delete; virtual;
// \Delete all nodes that are empty (this means, which have no subnodes, no
// attributes, and no value assigned). This procedure works recursively.
procedure DeleteEmptyNodes;
// Destroy a TXmlNode object. This will free the child node list automatically.
// Never call this method directly. All TXmlNodes in the document will be
// recursively freed when TNativeXml.Free is called.
destructor Destroy; override;
// Use this method to add an integer attribute to the node.
procedure AttributeAdd(const AName: UTF8String; AValue: integer); overload;
// Use this method to add a string attribute with value AValue to the node.
procedure AttributeAdd(const AName, AValue: UTF8String); overload;
// Use this method to delete the attribute at Index in the list. Index must be
// equal or greater than 0, and smaller than AttributeCount. Using an index
// outside of that range has no effect.
procedure AttributeDelete(Index: integer);
// Switch position of the attributes at Index1 and Index2.
procedure AttributeExchange(Index1, Index2: integer);
// Use this method to find the index of an attribute with name AName.
function AttributeIndexByname(const AName: UTF8String): integer;
// \Clear all attributes from the current node.
procedure AttributesClear; virtual;
// Use this method to read binary data from the node into Buffer with a length of Count.
procedure BufferRead(var Buffer{$IFDEF CLR}: TBytes{$ENDIF}; Count: Integer); virtual;
// Use this method to write binary data in Buffer with a length of Count to the
// current node. The data will appear as text using either BinHex or Base64
// method) in the final XML document.
// Notice that NativeXml does only support up to 2Gb bytes of data per file,
// so do not use this option for huge files. The binary encoding method (converting
// binary data into text) can be selected using property BinaryEncoding.
// xbeBase64 is most efficient, but slightly slower. Always use identical methods
// for reading and writing.
procedure BufferWrite(const Buffer{$IFDEF CLR}: TBytes{$ENDIF}; Count: Integer); virtual;
// Returns the length of the data in the buffer, once it would be decoded by
// method xbeBinHex or xbeBase64. If BinaryEncoding is xbeSixBits, this function
// cannot be used. The length of the unencoded data is determined from the
// length of the encoded data. For xbeBinHex this is trivial (just half the
// length), for xbeBase64 this is more difficult (must use the padding characters)
function BufferLength: integer; virtual;
// Clear all child nodes and attributes, and the name and value of the current
// XML node. However, the node is not deleted. Call Delete instead for that.
procedure Clear; virtual;
// Find the first node which has name NodeName. Contrary to the NodeByName
// function, this function will search the whole subnode tree, using the
// DepthFirst method. It is possible to search for a full path too, e.g.
// FoundNode := MyNode.FindNode('/Root/SubNode1/SubNode2/ThisNode');
function FindNode(const NodeName: UTF8String): TXmlNode;
// Find all nodes which have name NodeName. Contrary to the NodesByName
// function, this function will search the whole subnode tree. If you use
// a TXmlNodeList for the AList parameter, you don't need to cast the list
// items to TXmlNode.
procedure FindNodes(const NodeName: UTF8String; const AList: TList);
// Use FromAnsiString to convert a normal ANSI String to a UTF8String for the node
// (name, value, attributes). In TNativeXml the ANSI Characters are encoded
// into UTF8.
function FromAnsiString(const s: AnsiString): UTF8String;
// Use FromUnicodeString to convert UnicodeString to a UTF8String for the node (name, value,
// attributes).
function FromUnicodeString(const W: UnicodeString): UTF8String;
// Use HasAttribute to determine if the node has an attribute with name AName.
function HasAttribute(const AName: UTF8String): boolean; virtual;
// This function returns the index of this node in the parent's node list.
// If Parent is not assigned, this function returns -1.
function IndexInParent: integer;
// This function returns True if the node has no subnodes and no attributes,
// and if the node Name and value are empty.
function IsClear: boolean; virtual;
// This function returns True if the node has no subnodes and no attributes,
// and if the node value is empty.
function IsEmpty: boolean; virtual;
function IsEqualTo(ANode: TXmlNode; Options: TXmlCompareOptions; MismatchNodes: TList = nil): boolean;
// Add the node ANode as a new subelement in the nodelist. The node will be
// added in position NodeCount (which will be returned).
function NodeAdd(ANode: TXmlNode): integer; virtual;
// This function returns a pointer to the first subnode that has an attribute with
// name AttribName and value AttribValue. If ShouldRecurse = True (default), the
// function works recursively, using the depthfirst method.
function NodeByAttributeValue(const NodeName, AttribName, AttribValue: UTF8String;
ShouldRecurse: boolean = True): TXmlNode;
// Return a pointer to the first subnode with this Elementype, or return nil
// if no subnode with that type is found.
function NodeByElementType(ElementType: TXmlElementType): TXmlNode;
// Return a pointer to the first subnode in the nodelist that has name AName.
// If no subnodes with AName are found, the function returns nil.
function NodeByName(const AName: UTF8String): TXmlNode; virtual;
// \Delete the subnode at Index. The node will also be freed, so do not free the
// node in the application.
procedure NodeDelete(Index: integer); virtual;
// Switch position of the nodes at Index1 and Index2.
procedure NodeExchange(Index1, Index2: integer);
// Extract the node ANode from the subnode list. The node will no longer appear
// in the subnodes list, so the application is responsible for freeing ANode later.
function NodeExtract(ANode: TXmlNode): TXmlNode; virtual;
// This function returns a pointer to the first node with AName. If this node
// is not found, then it creates a new node with AName and returns its pointer.
function NodeFindOrCreate(const AName: UTF8String): TXmlNode; virtual;
// Find the index of the first subnode with name AName.
function NodeIndexByName(const AName: UTF8String): integer; virtual;
// Find the index of the first subnode with name AName that appears after or on
// the index AFrom. This function can be used in a loop to retrieve all nodes
// with a certain name, without using a helper list. See also NodesByName.
function NodeIndexByNameFrom(const AName: UTF8String; AFrom: integer): integer; virtual;
// Call NodeIndexOf to get the index for ANode in the Nodes array. The first
// node in the array has index 0, the second item has index 1, and so on. If
// a node is not in the list, NodeIndexOf returns -1.
function NodeIndexOf(ANode: TXmlNode): integer;
// Insert the node ANode at location Index in the list.
procedure NodeInsert(Index: integer; ANode: TXmlNode); virtual;
// \Create a new node with AName, add it to the subnode list, and return a
// pointer to it.
function NodeNew(const AName: UTF8String): TXmlNode; virtual;
// \Create a new node with AName, and insert it into the subnode list at location
// Index, and return a pointer to it.
function NodeNewAtIndex(Index: integer; const AName: UTF8String): TXmlNode; virtual;
// Call NodeRemove to remove a specific node from the Nodes array when its index
// is unknown. The value returned is the index of the item in the Nodes array
// before it was removed. After an item is removed, all the items that follow
// it are moved up in index position and the NodeCount is reduced by one.
function NodeRemove(ANode: TxmlNode): integer;
// \Clear (and free) the complete list of subnodes.
procedure NodesClear; virtual;
// Use this procedure to retrieve all nodes that have name AName. Pointers to
// these nodes are added to the list in AList. AList must be initialized
// before calling this procedure. If you use a TXmlNodeList you don't need
// to cast the list items to TXmlNode.
procedure NodesByName(const AName: UTF8String; const AList: TList);
// Find the attribute with AName, and convert its value to a boolean. If the
// attribute is not found, or cannot be converted, the default ADefault will
// be returned.
function ReadAttributeBool(const AName: UTF8String; ADefault: boolean = False): boolean; virtual;
function ReadAttributeDateTime(const AName: UTF8String; ADefault: TDateTime = 0): TDateTime; virtual;
// Find the attribute with AName, and convert its value to an integer. If the
// attribute is not found, or cannot be converted, the default ADefault will
// be returned.
function ReadAttributeInteger(const AName: UTF8String; ADefault: integer = 0): integer; virtual;
// Find the attribute with AName, and convert its value to an int64. If the
// attribute is not found, or cannot be converted, the default ADefault will
// be returned.
function ReadAttributeInt64(const AName: UTF8String; ADefault: int64 = 0): int64; virtual;
// Find the attribute with AName, and convert its value to a float. If the
// attribute is not found, or cannot be converted, the default ADefault will
// be returned.
function ReadAttributeFloat(const AName: UTF8String; ADefault: double = 0): double;
function ReadAttributeString(const AName: UTF8String; const ADefault: UTF8String = ''): UTF8String; virtual;
// Read the subnode with AName and convert it to a boolean value. If the
// subnode is not found, or cannot be converted, the boolean ADefault will
// be returned.
function ReadBool(const AName: UTF8String; ADefault: boolean = False): boolean; virtual;
{$IFDEF USEGRAPHICS}
// Read the properties Color and Style for the TBrush object ABrush from the
// subnode with AName.
procedure ReadBrush(const AName: UTF8String; ABrush: TBrush); virtual;
// Read the subnode with AName and convert its value to TColor. If the
// subnode is not found, or cannot be converted, ADefault will be returned.
function ReadColor(const AName: UTF8String; ADefault: TColor = clBlack): TColor; virtual;
// Read the properties \Name, Color, Size and Style for the TFont object AFont
// from the subnode with AName.
procedure ReadFont(const AName: UTF8String; AFont: TFont); virtual;
// Read the properties Color, Mode, Style and Width for the TPen object APen
// from the subnode with AName.
procedure ReadPen(const AName: UTF8String; APen: TPen); virtual;
{$ENDIF}
// Read the subnode with AName and convert its value to TDateTime. If the
// subnode is not found, or cannot be converted, ADefault will be returned.
function ReadDateTime(const AName: UTF8String; ADefault: TDateTime = 0): TDateTime; virtual;
// Read the subnode with AName and convert its value to a double. If the
// subnode is not found, or cannot be converted, ADefault will be returned.
function ReadFloat(const AName: UTF8String; ADefault: double = 0.0): double; virtual;
// Read the subnode with AName and convert its value to an int64. If the
// subnode is not found, or cannot be converted, ADefault will be returned.
function ReadInt64(const AName: UTF8String; ADefault: int64 = 0): int64; virtual;
// Read the subnode with AName and convert its value to an integer. If the
// subnode is not found, or cannot be converted, ADefault will be returned.
function ReadInteger(const AName: UTF8String; ADefault: integer = 0): integer; virtual;
// Read the subnode with AName and return its UTF8String value. If the subnode is
// not found, ADefault will be returned.
function ReadString(const AName: UTF8String; const ADefault: UTF8String = ''): UTF8String; virtual;
// Read the subnode with AName and return its UnicodeString value. If the subnode is
// not found, ADefault will be returned.
function ReadUnicodeString(const AName: UTF8String; const ADefault: UnicodeString = ''): UnicodeString; virtual;
// Sort the child nodes of this node. Provide a custom node compare function in Compare,
// or attach an event handler to the parent documents' OnNodeCompare in order to
// provide custom sorting. If no compare function is given (nil) and OnNodeCompare
// is not implemented, SortChildNodes will simply sort the nodes by name (ascending,
// case insensitive). The Info pointer parameter can be used to pass any custom
// information to the compare function. Default value for Info is nil.
procedure SortChildNodes(Compare: TXMLNodeCompareFunction = nil; Info: TPointer = nil);
// Use ToUnicodeString to convert any UTF8 String from the node (name, value, attributes)
// to a UnicodeString.
function ToUnicodeString(const s: UTF8String): UnicodeString;
// Convert the node's value to boolean and return the result. If this conversion
// fails, or no value is found, then the function returns ADefault.
function ValueAsBoolDef(ADefault: boolean): boolean; virtual;
// Convert the node's value to a TDateTime and return the result. If this conversion
// fails, or no value is found, then the function returns ADefault.
function ValueAsDateTimeDef(ADefault: TDateTime): TDateTime; virtual;
// Convert the node's value to a double and return the result. If this conversion
// fails, or no value is found, then the function returns ADefault.
function ValueAsFloatDef(ADefault: double): double; virtual;
// Convert the node's value to int64 and return the result. If this conversion
// fails, or no value is found, then the function returns ADefault.
function ValueAsInt64Def(ADefault: int64): int64; virtual;
// Convert the node's value to integer and return the result. If this conversion
// fails, or no value is found, then the function returns ADefault.
function ValueAsIntegerDef(ADefault: integer): integer; virtual;
// If the attribute with name AName exists, then set its value to the boolean
// AValue. If it does not exist, then create a new attribute AName with the
// boolean value converted to either "True" or "False". If ADefault = AValue, and
// WriteOnDefault = False, no attribute will be added.
procedure WriteAttributeBool(const AName: UTF8String; AValue: boolean; ADefault: boolean = False); virtual;
procedure WriteAttributeDateTime(const AName: UTF8string; AValue: TDateTime; ADefault: TDateTime = 0); virtual;
// If the attribute with name AName exists, then set its value to the integer
// AValue. If it does not exist, then create a new attribute AName with the
// integer value converted to a quoted string. If ADefault = AValue, and
// WriteOnDefault = False, no attribute will be added.
procedure WriteAttributeInteger(const AName: UTF8String; AValue: integer; ADefault: integer = 0); virtual;
procedure WriteAttributeInt64(const AName: UTF8String; const AValue: int64; ADefault: int64 = 0); virtual;
procedure WriteAttributeFloat(const AName: UTF8String; AValue: double; ADefault: double = 0); virtual;
// If the attribute with name AName exists, then set its value to the UTF8String
// AValue. If it does not exist, then create a new attribute AName with the
// value AValue. If ADefault = AValue, and WriteOnDefault = False, no attribute
// will be added.
procedure WriteAttributeString(const AName: UTF8String; const AValue: UTF8String; const ADefault: UTF8String = ''); virtual;
// Add or replace the subnode with AName and set its value to represent the boolean
// AValue. If AValue = ADefault, and WriteOnDefault = False, no subnode will be added.
procedure WriteBool(const AName: UTF8String; AValue: boolean; ADefault: boolean = False); virtual;
{$IFDEF USEGRAPHICS}
// Write properties Color and Style of the TBrush object ABrush to the subnode
// with AName. If AName does not exist, it will be created.
procedure WriteBrush(const AName: UTF8String; ABrush: TBrush); virtual;
// Add or replace the subnode with AName and set its value to represent the TColor
// AValue. If AValue = ADefault, and WriteOnDefault = False, no subnode will be added.
procedure WriteColor(const AName: UTF8String; AValue: TColor; ADefault: TColor = clBlack); virtual;
// Write properties \Name, Color, Size and Style of the TFont object AFont to
// the subnode with AName. If AName does not exist, it will be created.
procedure WriteFont(const AName: UTF8String; AFont: TFont); virtual;
// Write properties Color, Mode, Style and Width of the TPen object APen to
// the subnode with AName. If AName does not exist, it will be created.
procedure WritePen(const AName: UTF8String; APen: TPen); virtual;
{$ENDIF}
// Add or replace the subnode with AName and set its value to represent the TDateTime
// AValue. If AValue = ADefault, and WriteOnDefault = False, no subnode will be added.
// The XML format used is compliant with W3C's specification of date and time.
procedure WriteDateTime(const AName: UTF8String; AValue: TDateTime; ADefault: TDateTime = 0); virtual;
// Add or replace the subnode with AName and set its value to represent the double
// AValue. If AValue = ADefault, and WriteOnDefault = False, no subnode will be added.
procedure WriteFloat(const AName: UTF8String; AValue: double; ADefault: double = 0.0); virtual;
// Add or replace the subnode with AName and set its value to represent the hexadecimal representation of
// AValue. If AValue = ADefault, and WriteOnDefault = False, no subnode will be added.
procedure WriteHex(const AName: UTF8String; AValue: integer; Digits: integer; ADefault: integer = 0); virtual;
// Add or replace the subnode with AName and set its value to represent the int64
// AValue. If AValue = ADefault, and WriteOnDefault = False, no subnode will be added.
procedure WriteInt64(const AName: UTF8String; AValue: int64; ADefault: int64 = 0); virtual;
// Add or replace the subnode with AName and set its value to represent the integer
// AValue. If AValue = ADefault, and WriteOnDefault = False, no subnode will be added.
procedure WriteInteger(const AName: UTF8String; AValue: integer; ADefault: integer = 0); virtual;
// Add or replace the subnode with AName and set its value to represent the UTF8String
// AValue. If AValue = ADefault, and WriteOnDefault = False, no subnode will be added.
procedure WriteString(const AName, AValue: UTF8String; const ADefault: UTF8String = ''); virtual;
// Call WriteToString to save the XML node to a UTF8String. This method can be used to store
// individual nodes instead of the complete XML document.
function WriteToString: UTF8String; virtual;
// Add or replace the subnode with AName and set its value to represent the UnicodeString
// AValue. If AValue = ADefault, and WriteOnDefault = False, no subnode will be added.
procedure WriteUnicodeString(const AName: UTF8String; const AValue: UnicodeString; const ADefault: UnicodeString = ''); virtual;
// AttributeByName returns the attribute value for the attribute that has name AName.
// Set AttributeByName to add an attribute to the attribute list, or replace an
// existing one.
property AttributeByName[const AName: UTF8String]: UTF8String read GetAttributeByName write
SetAttributeByName;
// AttributeByNameWide returns the attribute value for the attribute that has name AName
// as UnicodeString. Set AttributeByNameWide to add an attribute to the attribute list, or replace an
// existing one.
property AttributeByNameWide[const AName: UTF8String]: UnicodeString read GetAttributeByNameWide write
SetAttributeByNameWide;
// Returns the number of attributes in the current node.
property AttributeCount: integer read GetAttributeCount;
// Read this property to get the name of the attribute at Index. Note that Index
// is zero-based: Index goes from 0 to AttributeCount - 1
property AttributeName[Index: integer]: UTF8String read GetAttributeName write SetAttributeName;
// Read this property to get the Attribute \Name and Value pair at index Index.
// This is a UTF8String with \Name and Value separated by a TAB character (#9).
property AttributePair[Index: integer]: UTF8String read GetAttributePair;
// Read this property to get the UTF8String value of the attribute at index Index.
// Write to it to set the UTF8String value.
property AttributeValue[Index: integer]: UTF8String read GetAttributeValue write SetAttributeValue;
// Read this property to get the UnicodeString value of the attribute at index Index.
// Write to it to set the UnicodeString value.
property AttributeValueAsUnicodeString[Index: integer]: UnicodeString read GetAttributeValueAsUnicodeString write SetAttributeValueAsUnicodeString;
// Read this property to get the integer value of the attribute at index Index.
// If the value cannot be converted, 0 will be returned. Write to it to set the integer value.
property AttributeValueAsInteger[Index: integer]: integer read GetAttributeValueAsInteger write SetAttributeValueAsInteger;
// Set or get the raw attribute value, thus circumventing the escape function. Make sure that
// the value you set does not contain the & and quote AnsiCharacters, or the produced
// XML will be invalid.
property AttributeValueDirect[Index: integer]: UTF8String read GetAttributeValueDirect write SetAttributeValueDirect;
// BinaryEncoding reflects the same value as the BinaryEncoding setting of the parent
// Document.
property BinaryEncoding: TBinaryEncodingType read GetBinaryEncoding write SetBinaryEncoding;
// Use BinaryString to add/extract binary data in an easy way to/from the node. Internally the
// data gets stored as Base64-encoded data. Do not use this method for normal textual
// information, it is better to use ValueAsString in that case (adds less overhead).
property BinaryString: RawByteString read GetBinaryString write SetBinaryString;
// This property returns the name and index and all predecessors with underscores
// to separate, in order to get a unique reference that can be used in filenames.
property CascadedName: UTF8String read GetCascadedName;
// Pointer to parent NativeXml document, or Nil if none.
property Document: TNativeXml read FDocument write FDocument;
// ElementType contains the type of element that this node holds.
property ElementType: TXmlElementType read FElementType write FElementType;
// Fullpath will return the complete path of the node from the root, e.g.
// /Root/SubNode1/SubNode2/ThisNode
property FullPath: UTF8String read GetFullPath;
// Read Name to get the name of the element, and write Name to set the name.
// This is the full name and may include a namespace. (Namespace:Name)
property Name: UTF8String read FName write SetName;
// Parent points to the parent node of the current XML node.
property Parent: TXmlNode read FParent write FParent;
// NodeCount is the number of child nodes that this node holds. In order to
// loop through all child nodes, use a construct like this:
// <CODE>
// with MyNode do
// for i := 0 to NodeCount - 1 do
// with Nodes[i] do
// ..processing here
// </CODE>
property NodeCount: integer read GetNodeCount;
// Use Nodes to access the child nodes of the current XML node by index. Note
// that the list is zero-based, so Index is valid from 0 to NodeCount - 1.
property Nodes[Index: integer]: TXmlNode read GetNodes; default;
// Tag is an integer value the developer can use in any way. Tag does not get
// saved to the XML. Tag is often used to point to a GUI element (and is then
// cast to a pointer).
property Tag: integer read FTag write FTag;
// TotalNodeCount represents the total number of child nodes, and child nodes
// of child nodes etcetera of this particular node. Use the following to get
// the total number of nodes in the XML document:
// <CODE>
// Total := MyDoc.RootNodes.TotalNodeCount;
// </CODE>
property TotalNodeCount: integer read GetTotalNodeCount;
// Read TreeDepth to find out many nested levels there are for the current XML
// node. Root has a TreeDepth of zero.
property TreeDepth: integer read GetTreeDepth;
// ValueAsBool returns the node's value as boolean, or raises an
// exception if the value cannot be converted to boolean. Set ValueAsBool
// to convert a boolean to a UTF8String in the node's value field. See also
// function ValueAsBoolDef.
property ValueAsBool: boolean read GetValueAsBool write SetValueAsBool;
// ValueAsDateTime returns the node's value as TDateTime, or raises an
// exception if the value cannot be converted to TDateTime. Set ValueAsDateTime
// to convert a TDateTime to a UTF8String in the node's value field. See also
// function ValueAsDateTimeDef.
property ValueAsDateTime: TDateTime read GetValueAsDateTime write SetValueAsDateTime;
// ValueAsIn64 returns the node's value as int64, or raises an
// exception if the value cannot be converted to int64. Set ValueAsInt64
// to convert an int64 to a UTF8String in the node's value field. See also
// function ValueAsInt64Def.
property ValueAsInt64: int64 read GetValueAsInt64 write SetValueAsInt64;
// ValueAsInteger returns the node's value as integer, or raises an
// exception if the value cannot be converted to integer. Set ValueAsInteger
// to convert an integer to a UTF8String in the node's value field. See also
// function ValueAsIntegerDef.
property ValueAsInteger: integer read GetValueAsInteger write SetValueAsInteger;
// ValueAsFloat returns the node's value as float, or raises an
// exception if the value cannot be converted to float. Set ValueAsFloat
// to convert a float to a UTF8String in the node's value field. See also
// function ValueAsFloatDef.
property ValueAsFloat: double read GetValueAsFloat write SetValueAsFloat;
// ValueAsString returns the unescaped version of ValueDirect. All neccesary
// characters in ValueDirect must be escaped (e.g. "&" becomes "&") but
// ValueAsString returns them in original format. Always use ValueAsString to
// set the text value of a node, to make sure all neccesary charaters are
// escaped.
property ValueAsString: UTF8String read GetValueAsString write SetValueAsString;
// ValueAsUnicodeString returns the unescaped version of ValueDirect as a UnicodeString.
// Always use ValueAsUnicodeString to set the text value of a node, to make sure all
// neccesary charaters are escaped.
property ValueAsUnicodeString: UnicodeString read GetValueAsUnicodeString write SetValueAsUnicodeString;
// ValueDirect is the exact text value as was parsed from the stream. If multiple
// text elements are encountered, they are added to ValueDirect with a CR to
// separate them.
property ValueDirect: UTF8String read FValue write FValue;
// WriteOnDefault reflects the same value as the WriteOnDefault setting of the parent
// Document.
property WriteOnDefault: boolean read GetWriteOnDefault;
end;
// TXmlNodeList is a utility TList descendant that can be used to work with selection
// lists. An example:
// <code>
// procedure FindAllZips(ANode: TXmlNode);
// var
// i: integer;
// AList: TXmlNodeList;
// begin
// AList := TXmlNodeList.Create;
// try
// // Get a list of all nodes named 'ZIP'
// ANode.NodesByName('ZIP', AList);
// for i := 0 to AList.Count - 1 do
// // Write the value of the node to output. Since AList[i] will be
// // of type TXmlNode, we can directly access the Value property.
// WriteLn(AList[i].Value);
// finally
// AList.Free;
// end;
// end;
// </code>
TXmlNodeList = class(TList)
private
function GetItems(Index: Integer): TXmlNode;
procedure SetItems(Index: Integer; const Value: TXmlNode);
public
// Return the first node in the list that has an attribute with AName, AValue
function ByAttribute(const AName, AValue: UTF8String): TXmlNode;
property Items[Index: Integer]: TXmlNode read GetItems write SetItems; default;
end;
// TNativeXml is the XML document holder. Create a TNativeXml and then use
// methods LoadFromFile, LoadFromStream or ReadFromString to load an XML document
// into memory. Or start from scratch and use Root.NodeNew to add nodes and
// eventually SaveToFile and SaveToStream to save the results as an XML document.
// Use property Xmlformat = xfReadable to ensure that indented (readable) output
// is produced.
TNativeXml = class(TPersistent)
private
FAbortParsing: boolean; // Signal to abort the parsing process
FBinaryEncoding: TBinaryEncodingType; // xbeBinHex or xbeBase64
FCodecStream: TsdCodecStream; // Temporary stream used to read encoded files
FDropCommentsOnParse: boolean; // If true, comments are dropped (deleted) when parsing
FExternalEncoding: TStringEncodingType;
FFloatAllowScientific: boolean;
FFloatSignificantDigits: integer;
FParserWarnings: boolean; // Show parser warnings for non-critical errors
FRootNodes: TXmlNode; // Root nodes in the document (which contains one normal element that is the root)
FIndentString: UTF8String; // The indent string used to indent content (default is two spaces)
FUseFullNodes: boolean; // If true, nodes are never written in short notation.
FWriteOnDefault: boolean; // Set this option to "False" to only write values <> default value (default = true)
FXmlFormat: TXmlFormatType; // xfReadable, xfCompact
FOnNodeCompare: TXmlNodeCompareEvent; // Compare two nodes
FOnNodeNew: TXmlNodeEvent; // Called after a node is added
FOnNodeLoaded: TXmlNodeEvent; // Called after a node is loaded completely
FOnProgress: TXmlProgressEvent; // Called after a node is loaded/saved, with the current position in the file
FOnUnicodeLoss: TNotifyEvent; // This event is called when there is a warning for unicode conversion loss when reading unicode
procedure DoNodeNew(Node: TXmlNode);
procedure DoNodeLoaded(Node: TXmlNode);
procedure DoUnicodeLoss(Sender: TObject);
function GetCommentString: UTF8String;
procedure SetCommentString(const Value: UTF8String);
function GetEntityByName(AName: UTF8String): UTF8String;
function GetRoot: TXmlNode;
function GetEncodingString: UTF8String;
procedure SetEncodingString(const Value: UTF8String);
function GetVersionString: UTF8String;
procedure SetVersionString(const Value: UTF8String);
function GetStyleSheetNode: TXmlNode;
function GetUtf8Encoded: boolean;
protected
procedure CopyFrom(Source: TNativeXml); virtual;
procedure DoProgress(Size: integer);
function LineFeed: UTF8String; virtual;
procedure ParseDTD(ANode: TXmlNode; S: TStream); virtual;
procedure ReadFromStream(S: TStream); virtual;
procedure WriteToStream(S: TStream); virtual;
procedure SetDefaults; virtual;
public
// Create a new NativeXml document which can then be used to read or write XML files.
// A document that is created with Create must later be freed using Free.
// Example:
// <Code>
// var
// ADoc: TNativeXml;
// begin
// ADoc := TNativeXml.Create;
// try
// ADoc.LoadFromFile('c:\\temp\\myxml.xml');
// {do something with the document here}
// finally
// ADoc.Free;
// end;
// end;
// </Code>
constructor Create; virtual;
// Use CreateName to Create a new Xml document that will automatically
// contain a root element with name ARootName.
constructor CreateName(const ARootName: UTF8String); virtual;
// Destroy will free all data in the TNativeXml object. This includes the
// root node and all subnodes under it. Do not call Destroy directly, call
// Free instead.
destructor Destroy; override;
// When calling Assign with a Source object that is a TNativeXml, will cause
// it to copy all data from Source.
procedure Assign(Source: TPersistent); override;
// Call Clear to remove all data from the object, and restore all defaults.
procedure Clear; virtual;
// Function IsEmpty returns true if the root is clear, or in other words, the
// root contains no value, no name, no subnodes and no attributes.
function IsEmpty: boolean; virtual;
// Load an XML document from the TStream object in Stream. The LoadFromStream
// procedure will raise an exception of type EFilerError when it encounters
// non-wellformed XML. This method can be used with any TStream descendant.
// See also LoadFromFile and ReadFromString.
procedure LoadFromStream(Stream: TStream); virtual;
// Call procedure LoadFromFile to load an XML document from the filename
// specified. See Create for an example. The LoadFromFile procedure will raise
// an exception of type EFilerError when it encounters non-wellformed XML.
procedure LoadFromFile(const AFileName: string); virtual;
// Call procedure ReadFromString to load an XML document from the UTF8String AValue.
// The ReadFromString procedure will raise an exception of type EFilerError
// when it encounters non-wellformed XML.
procedure ReadFromString(const AValue: UTF8String); virtual;
// Call ResolveEntityReferences after the document has been loaded to resolve
// any present entity references (&Entity;). When an entity is found in the
// DTD, it will replace the entity reference. Whenever an entity contains
// XML markup, it will be parsed and become part of the document tree. Since
// calling ResolveEntityReferences is adding quite some extra overhead, it
// is not done automatically. If you want to do the entity replacement, a good
// moment to call ResolveEntityReferences is right after LoadFromFile.
procedure ResolveEntityReferences;
// Call SaveToStream to save the XML document to the Stream. Stream
// can be any TStream descendant. Set XmlFormat to xfReadable if you want
// the stream to contain indentations to make the XML more human-readable. This
// is not the default and also not compliant with the XML specification. See
// SaveToFile for information on how to save in special encoding.
procedure SaveToStream(Stream: TStream); virtual;
// Call SaveToFile to save the XML document to a file with FileName. If the
// filename exists, it will be overwritten without warning. If the file cannot
// be created, a standard I/O exception will be generated. Set XmlFormat to
// xfReadable if you want the file to contain indentations to make the XML
// more human-readable. This is not the default and also not compliant with
// the XML specification.<p>
// Saving to special encoding types can be achieved by setting two properties
// before saving:
// * ExternalEncoding
// * EncodingString
// ExternalEncoding can be se8bit (for plain ascii), seUtf8 (UTF-8), seUtf16LE
// (for unicode) or seUtf16BE (unicode big endian).<p> Do not forget to also
// set the EncodingString (e.g. "UTF-8" or "UTF-16") which matches with your
// ExternalEncoding.
procedure SaveToFile(const AFileName: string); virtual;
// Call WriteToString to save the XML document to a UTF8String. Set XmlFormat to
// xfReadable if you want the UTF8String to contain indentations to make the XML
// more human-readable. This is not the default and also not compliant with
// the XML specification.
function WriteToString: UTF8String; virtual;
// Set AbortParsing to True if you use the OnNodeNew and OnNodeLoaded events in
// a SAX-like manner, and you want to abort the parsing process halfway. Example:
// <code>
// procedure MyForm.NativeXmlNodeLoaded(Sender: TObject; Node: TXmlNode);
// begin
// if (Node.Name = 'LastNode') and (Sender is TNativeXml) then
// TNativeXml(Sender).AbortParsing := True;
// end;
// </code>
property AbortParsing: boolean read FAbortParsing write FAbortParsing;
// Choose what kind of binary encoding will be used when calling TXmlNode.BufferRead
// and TXmlNode.BufferWrite. Default value is xbeBase64.
property BinaryEncoding: TBinaryEncodingType read FBinaryEncoding write FBinaryEncoding;
// A comment string above the root element \<!--{comment}--\> can be accessed with
// this property. \Assign a comment to this property to add it to the XML document.
// Use property RootNodeList to add/insert/extract multiple comments.
property CommentString: UTF8String read GetCommentString write SetCommentString;
// Set DropCommentsOnParse if you're not interested in any comment nodes in your object
// model data. All comments encountered during parsing will simply be skipped and
// not added as a node with ElementType = xeComment (which is default). Note that
// when you set this option, you cannot later reconstruct an XML file with the comments
// back in place.
property DropCommentsOnParse: boolean read FDropCommentsOnParse write FDropCommentsOnParse;
// Encoding string (e.g. "UTF-8" or "UTF-16"). This encoding string is stored in
// the header.
// Example: In order to get this header:
// <?xml version="1.0" encoding="UTF-16" ?>
// enter this code:
// <CODE>MyXmlDocument.EncodingString := 'UTF-16';</CODE>
// When reading a file, EncodingString will contain the encoding used.
property EncodingString: UTF8String read GetEncodingString write SetEncodingString;
// Returns the value of the named entity in Name, where name should be stripped
// of the leading & and trailing ;. These entity values are parsed from the
// Doctype declaration (if any).
property EntityByName[AName: UTF8String]: UTF8String read GetEntityByName;
// ExternalEncoding defines in which format XML files are saved. Set ExternalEncoding
// to se8bit to save as plain text files, to seUtf8 to save as UTF8 files (with
// Byte Order Mark #EF BB FF) and to seUTF16LE to save as unicode (Byte Order
// Mark #FF FE). When reading an XML file, the value of ExternalEncoding will
// be set according to the byte order mark and/or encoding declaration found.
property ExternalEncoding: TStringEncodingType read FExternalEncoding write FExternalEncoding;
// When converting floating point values to strings (e.g. in WriteFloat),
// NativeXml will allow to output scientific notation in some cases, if the
// result is significantly shorter than normal output, but only if the value
// of FloatAllowScientific is True (default).
property FloatAllowScientific: boolean read FFloatAllowScientific write FFloatAllowScientific;
// When converting floating point values to strings (e.g. in WriteFloat),
// NativeXml will use this number of significant digits. The default is
// cDefaultFloatSignificantDigits, and set to 6.
property FloatSignificantDigits: integer read FFloatSignificantDigits write FFloatSignificantDigits;
// IndentString is the string used for indentations. By default, it is two
// spaces: ' '. Set IndentString to something else if you need to have
// specific indentation, or set it to an empty string to avoid indentation.
property IndentString: UTF8String read FIndentString write FIndentString;
// Root is the topmost element in the XML document. Access Root to read any
// child elements. When creating a new XML document, you can automatically
// include a Root node, by creating using CreateName.