3
This is a TEMPORARY file.
4
As soon as it is moved to the fcl, it will be removed.
8
$Id: laz_dom.pas 29456 2011-02-10 22:22:30Z vincents $
9
This file is part of the Free Component Library
11
Implementation of DOM interfaces
12
Copyright (c) 1999-2000 by Sebastian Guenther, sg@freepascal.org
14
See the file COPYING.modifiedLGPL.txt, included in this distribution,
15
for details about the copyright.
17
This program is distributed in the hope that it will be useful,
18
but WITHOUT ANY WARRANTY; without even the implied warranty of
19
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
21
**********************************************************************}
24
This unit provides classes which implement the interfaces defined in the
25
DOM (Document Object Model) specification.
27
DOM Level 1 - Almost completely implemented
28
DOM Level 2 - Partially implemented
31
Specification used for this implementation:
33
"Document Object Model (DOM) Level 2 Specification Version 1.0
34
W3C Candidate Recommendation 07 March, 2000"
35
http://www.w3.org/TR/2000/CR-DOM-Level-2-20000307
46
{off $DEFINE MEM_CHECK}
49
{$IFDEF MEM_CHECK}MemCheck,{$ENDIF}
50
SysUtils, Classes, Avl_Tree;
54
TDOMImplementation = class;
55
TDOMDocumentFragment = class;
59
TDOMNamedNodeMap = class;
60
TDOMCharacterData = class;
65
TDOMCDATASection = class;
66
TDOMDocumentType = class;
69
TDOMEntityReference = class;
70
TDOMProcessingInstruction = class;
73
// -------------------------------------------------------
75
// -------------------------------------------------------
78
// DOMString = WideString;
79
// DOMPChar = PWideChar;
82
// -------------------------------------------------------
84
// -------------------------------------------------------
89
// DOM Level 1 exception codes:
91
INDEX_SIZE_ERR = 1; // index or size is negative, or greater than the allowed value
92
DOMSTRING_SIZE_ERR = 2; // Specified range of text does not fit into a DOMString
93
HIERARCHY_REQUEST_ERR = 3; // node is inserted somewhere it does not belong
94
WRONG_DOCUMENT_ERR = 4; // node is used in a different document than the one that created it (that does not support it)
95
INVALID_CHARACTER_ERR = 5; // invalid or illegal character is specified, such as in a name
96
NO_DATA_ALLOWED_ERR = 6; // data is specified for a node which does not support data
97
NO_MODIFICATION_ALLOWED_ERR = 7; // an attempt is made to modify an object where modifications are not allowed
98
NOT_FOUND_ERR = 8; // an attempt is made to reference a node in a context where it does not exist
99
NOT_SUPPORTED_ERR = 9; // implementation does not support the type of object requested
100
INUSE_ATTRIBUTE_ERR = 10; // an attempt is made to add an attribute that is already in use elsewhere
102
// DOM Level 2 exception codes:
104
INVALID_STATE_ERR = 11; // an attempt is made to use an object that is not, or is no longer, usable
105
SYNTAX_ERR = 12; // invalid or illegal string specified
106
INVALID_MODIFICATION_ERR = 13; // an attempt is made to modify the type of the underlying object
107
NAMESPACE_ERR = 14; // an attempt is made to create or change an object in a way which is incorrect with regard to namespaces
108
INVALID_ACCESS_ERR = 15; // parameter or operation is not supported by the underlying object
113
EDOMError = class(Exception)
116
constructor Create(ACode: Integer; const ASituation: String);
119
EDOMIndexSize = class(EDOMError)
121
constructor Create(const ASituation: String);
124
EDOMHierarchyRequest = class(EDOMError)
126
constructor Create(const ASituation: String);
129
EDOMWrongDocument = class(EDOMError)
131
constructor Create(const ASituation: String);
134
EDOMNotFound = class(EDOMError)
136
constructor Create(const ASituation: String);
139
EDOMNotSupported = class(EDOMError)
141
constructor Create(const ASituation: String);
144
EDOMInUseAttribute = class(EDOMError)
146
constructor Create(const ASituation: String);
149
EDOMInvalidState = class(EDOMError)
151
constructor Create(const ASituation: String);
154
EDOMSyntax = class(EDOMError)
156
constructor Create(const ASituation: String);
159
EDOMInvalidModification = class(EDOMError)
161
constructor Create(const ASituation: String);
164
EDOMNamespace = class(EDOMError)
166
constructor Create(const ASituation: String);
169
EDOMInvalidAccess = class(EDOMError)
171
constructor Create(const ASituation: String);
175
// -------------------------------------------------------
177
// -------------------------------------------------------
184
CDATA_SECTION_NODE = 4;
185
ENTITY_REFERENCE_NODE = 5;
187
PROCESSING_INSTRUCTION_NODE = 7;
190
DOCUMENT_TYPE_NODE = 10;
191
DOCUMENT_FRAGMENT_NODE = 11;
202
function AddRef: LongInt; virtual;
203
function Release: LongInt; virtual;
210
FNodeName, FNodeValue: DOMString;
212
FParentNode: TDOMNode;
213
FPreviousSibling, FNextSibling: TDOMNode;
214
FOwnerDocument: TDOMDocument;
216
function GetNodeValue: DOMString; virtual;
217
procedure SetNodeValue(const AValue: DOMString); virtual;
218
function GetFirstChild: TDOMNode; virtual;
219
function GetLastChild: TDOMNode; virtual;
220
function GetAttributes: TDOMNamedNodeMap; virtual;
223
constructor Create(AOwner: TDOMDocument);
225
// Free NodeList with TDOMNodeList.Release!
226
function GetChildNodes: TDOMNodeList; virtual;
228
property NodeName: DOMString read FNodeName;
229
property NodeValue: DOMString read GetNodeValue write SetNodeValue;
230
property NodeType: Integer read FNodeType;
231
property ParentNode: TDOMNode read FParentNode;
232
property FirstChild: TDOMNode read GetFirstChild;
233
property LastChild: TDOMNode read GetLastChild;
234
property ChildNodes: TDOMNodeList read GetChildNodes;
235
property PreviousSibling: TDOMNode read FPreviousSibling;
236
property NextSibling: TDOMNode read FNextSibling;
237
property Attributes: TDOMNamedNodeMap read GetAttributes;
238
property OwnerDocument: TDOMDocument read FOwnerDocument;
240
function InsertBefore(NewChild, RefChild: TDOMNode): TDOMNode; virtual;
241
function ReplaceChild(NewChild, OldChild: TDOMNode): TDOMNode; virtual;
242
function RemoveChild(OldChild: TDOMNode): TDOMNode; virtual;
243
function AppendChild(NewChild: TDOMNode): TDOMNode; virtual;
244
function HasChildNodes: Boolean; virtual;
245
function CloneNode(deep: Boolean): TDOMNode; overload;
246
function IsEmpty: Boolean; virtual;
248
// Extensions to DOM interface:
249
function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; virtual;
250
function FindNode(const ANodeName: DOMString): TDOMNode; virtual;
254
{ The following class is an implementation specific extension, it is just an
255
extended implementation of TDOMNode, the generic DOM::Node interface
256
implementation. (Its main purpose is to save memory in a big node tree) }
258
TDOMNode_WithChildren = class(TDOMNode)
260
FFirstChild, FLastChild: TDOMNode;
261
FChildNodeTree: TAVLTree;// tree of TDOMNode sorted for Name (=> there can be doubles)
262
function GetFirstChild: TDOMNode; override;
263
function GetLastChild: TDOMNode; override;
264
procedure CloneChildren(ACopy: TDOMNode; ACloneOwner: TDOMDocument);
265
procedure AddToChildNodeTree(NewNode: TDOMNode);
266
procedure RemoveFromChildNodeTree(OldNode: TDOMNode);
268
destructor Destroy; override;
269
function InsertBefore(NewChild, RefChild: TDOMNode): TDOMNode; override;
270
function ReplaceChild(NewChild, OldChild: TDOMNode): TDOMNode; override;
271
function RemoveChild(OldChild: TDOMNode): TDOMNode; override;
272
function AppendChild(NewChild: TDOMNode): TDOMNode; override;
273
function HasChildNodes: Boolean; override;
274
function FindNode(const ANodeName: DOMString): TDOMNode; override;
278
// -------------------------------------------------------
280
// -------------------------------------------------------
282
TDOMNodeList = class(TRefClass)
287
function GetCount: LongInt;
288
function GetItem(index: LongWord): TDOMNode;
290
constructor Create(ANode: TDOMNode; const AFilter: DOMString);
291
property Item[index: LongWord]: TDOMNode read GetItem;
292
property Count: LongInt read GetCount;
296
// -------------------------------------------------------
298
// -------------------------------------------------------
300
TDOMNamedNodeMap = class(TFPList)
302
OwnerDocument: TDOMDocument;
303
function GetItem(index: LongWord): TDOMNode;
304
procedure SetItem(index: LongWord; AItem: TDOMNode);
305
function GetLength: LongInt;
307
constructor Create(AOwner: TDOMDocument);
309
function GetNamedItem(const name: DOMString): TDOMNode;
310
function SetNamedItem(arg: TDOMNode): TDOMNode;
311
function RemoveNamedItem(const name: DOMString): TDOMNode;
312
property Item[index: LongWord]: TDOMNode read GetItem write SetItem; default;
313
property Length: LongInt read GetLength;
317
// -------------------------------------------------------
319
// -------------------------------------------------------
321
TDOMCharacterData = class(TDOMNode)
323
function GetLength: LongInt;
325
property Data: DOMString read FNodeValue;
326
property Length: LongInt read GetLength;
327
function SubstringData(offset, count: LongWord): DOMString;
328
procedure AppendData(const arg: DOMString);
329
procedure InsertData(offset: LongWord; const arg: DOMString);
330
procedure DeleteData(offset, count: LongWord);
331
procedure ReplaceData(offset, count: LongWord; const arg: DOMString);
335
// -------------------------------------------------------
337
// -------------------------------------------------------
339
TDOMImplementation = class
341
function HasFeature(const feature, version: DOMString): Boolean;
343
// Introduced in DOM Level 2:
345
function CreateDocumentType(const QualifiedName, PublicID,
346
SystemID: DOMString): TDOMDocumentType;
347
function CreateDocument(const NamespaceURI, QualifiedName: DOMString;
348
doctype: TDOMDocumentType): TDOMDocument;
352
// -------------------------------------------------------
354
// -------------------------------------------------------
356
TDOMDocumentFragment = class(TDOMNode_WithChildren)
358
constructor Create(AOwner: TDOMDocument);
362
// -------------------------------------------------------
364
// -------------------------------------------------------
366
TDOMDocument = class(TDOMNode_WithChildren)
368
FDocType: TDOMDocumentType;
369
FImplementation: TDOMImplementation;
370
function GetDocumentElement: TDOMElement;
372
property DocType: TDOMDocumentType read FDocType;
373
property Impl: TDOMImplementation read FImplementation;
374
property DocumentElement: TDOMElement read GetDocumentElement;
376
function CreateElement(const tagName: DOMString): TDOMElement; virtual;
377
function CreateDocumentFragment: TDOMDocumentFragment;
378
function CreateTextNode(const data: DOMString): TDOMText;
379
function CreateComment(const data: DOMString): TDOMComment;
380
function CreateCDATASection(const data: DOMString): TDOMCDATASection;
382
function CreateProcessingInstruction(const target, data: DOMString):
383
TDOMProcessingInstruction; virtual;
384
function CreateAttribute(const name: DOMString): TDOMAttr; virtual;
385
function CreateEntityReference(const name: DOMString): TDOMEntityReference;
387
// Free NodeList with TDOMNodeList.Release!
388
function GetElementsByTagName(const tagname: DOMString): TDOMNodeList;
390
// Extensions to DOM interface:
392
function CreateEntity(const data: DOMString): TDOMEntity;
395
TXMLDocument = class(TDOMDocument)
397
// These fields are extensions to the DOM interface:
398
XMLVersion, Encoding, StylesheetType, StylesheetHRef: DOMString;
400
function CreateCDATASection(const data: DOMString): TDOMCDATASection; override;
401
function CreateProcessingInstruction(const target, data: DOMString):
402
TDOMProcessingInstruction; override;
403
function CreateEntityReference(const name: DOMString): TDOMEntityReference; override;
407
// -------------------------------------------------------
409
// -------------------------------------------------------
411
TDOMAttr = class(TDOMNode_WithChildren)
414
AttrOwner: TDOMNamedNodeMap;
415
function GetNodeValue: DOMString; override;
416
procedure SetNodeValue(const AValue: DOMString); override;
418
constructor Create(AOwner: TDOMDocument);
420
function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
421
property Name: DOMString read FNodeName;
422
property Specified: Boolean read FSpecified;
423
property Value: DOMString read GetNodeValue write SetNodeValue;
427
// -------------------------------------------------------
429
// -------------------------------------------------------
433
TDOMElement = class(TDOMNode_WithChildren)
435
FAttributes: TDOMNamedNodeMap;
437
function GetAttributes: TDOMNamedNodeMap; override;
439
constructor Create(AOwner: TDOMDocument);
440
destructor Destroy; override;
441
function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
442
property TagName: DOMString read FNodeName;
443
function GetAttribute(const name: DOMString): DOMString;
444
procedure SetAttribute(const name, value: DOMString);
445
procedure RemoveAttribute(const name: DOMString);
446
function GetAttributeNode(const name: DOMString): TDOMAttr;
447
procedure SetAttributeNode(NewAttr: TDOMAttr);
448
function RemoveAttributeNode(OldAttr: TDOMAttr): TDOMAttr;
449
// Free NodeList with TDOMNodeList.Release!
450
function GetElementsByTagName(const name: DOMString): TDOMNodeList;
451
function IsEmpty: Boolean; override;
454
property AttribStrings[const Name: DOMString]: DOMString
455
read GetAttribute write SetAttribute; default;
459
// -------------------------------------------------------
461
// -------------------------------------------------------
463
TDOMText = class(TDOMCharacterData)
465
constructor Create(AOwner: TDOMDocument);
466
function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
467
function SplitText(offset: LongWord): TDOMText;
471
// -------------------------------------------------------
473
// -------------------------------------------------------
475
TDOMComment = class(TDOMCharacterData)
477
constructor Create(AOwner: TDOMDocument);
478
function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
482
// -------------------------------------------------------
484
// -------------------------------------------------------
486
TDOMCDATASection = class(TDOMText)
488
constructor Create(AOwner: TDOMDocument);
489
function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
493
// -------------------------------------------------------
495
// -------------------------------------------------------
497
TDOMDocumentType = class(TDOMNode)
499
FEntities, FNotations: TDOMNamedNodeMap;
501
constructor Create(AOwner: TDOMDocument);
502
function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
503
property Name: DOMString read FNodeName;
504
property Entities: TDOMNamedNodeMap read FEntities;
505
property Notations: TDOMNamedNodeMap read FEntities;
509
// -------------------------------------------------------
511
// -------------------------------------------------------
513
TDOMNotation = class(TDOMNode)
515
FPublicID, FSystemID: DOMString;
517
constructor Create(AOwner: TDOMDocument);
518
function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
519
property PublicID: DOMString read FPublicID;
520
property SystemID: DOMString read FSystemID;
524
// -------------------------------------------------------
526
// -------------------------------------------------------
528
TDOMEntity = class(TDOMNode_WithChildren)
530
FPublicID, FSystemID, FNotationName: DOMString;
532
constructor Create(AOwner: TDOMDocument);
533
property PublicID: DOMString read FPublicID;
534
property SystemID: DOMString read FSystemID;
535
property NotationName: DOMString read FNotationName;
539
// -------------------------------------------------------
541
// -------------------------------------------------------
543
TDOMEntityReference = class(TDOMNode_WithChildren)
545
constructor Create(AOwner: TDOMDocument);
549
// -------------------------------------------------------
550
// ProcessingInstruction
551
// -------------------------------------------------------
553
TDOMProcessingInstruction = class(TDOMNode)
555
constructor Create(AOwner: TDOMDocument);
556
property Target: DOMString read FNodeName;
557
property Data: DOMString read FNodeValue;
563
// =======================================================
564
// =======================================================
569
constructor TRefClass.Create;
575
function TRefClass.AddRef: LongInt;
578
Result := RefCounter;
581
function TRefClass.Release: LongInt;
584
Result := RefCounter;
585
if RefCounter <= 0 then Free;
589
// -------------------------------------------------------
591
// -------------------------------------------------------
593
constructor EDOMError.Create(ACode: Integer; const ASituation: String);
596
inherited Create(Self.ClassName + ' in ' + ASituation);
599
constructor EDOMIndexSize.Create(const ASituation: String); // 1
601
inherited Create(INDEX_SIZE_ERR, ASituation);
604
constructor EDOMHierarchyRequest.Create(const ASituation: String); // 3
606
inherited Create(HIERARCHY_REQUEST_ERR, ASituation);
609
constructor EDOMWrongDocument.Create(const ASituation: String); // 4
611
inherited Create(WRONG_DOCUMENT_ERR, ASituation);
614
constructor EDOMNotFound.Create(const ASituation: String); // 8
616
inherited Create(NOT_FOUND_ERR, ASituation);
619
constructor EDOMNotSupported.Create(const ASituation: String); // 9
621
inherited Create(NOT_SUPPORTED_ERR, ASituation);
624
constructor EDOMInUseAttribute.Create(const ASituation: String); // 10
626
inherited Create(INUSE_ATTRIBUTE_ERR, ASituation);
629
constructor EDOMInvalidState.Create(const ASituation: String); // 11
631
inherited Create(INVALID_STATE_ERR, ASituation);
634
constructor EDOMSyntax.Create(const ASituation: String); // 12
636
inherited Create(SYNTAX_ERR, ASituation);
639
constructor EDOMInvalidModification.Create(const ASituation: String); // 13
641
inherited Create(INVALID_MODIFICATION_ERR, ASituation);
644
constructor EDOMNamespace.Create(const ASituation: String); // 14
646
inherited Create(NAMESPACE_ERR, ASituation);
649
constructor EDOMInvalidAccess.Create(const ASituation: String); // 15
651
inherited Create(INVALID_ACCESS_ERR, ASituation);
655
// -------------------------------------------------------
657
// -------------------------------------------------------
659
constructor TDOMNode.Create(AOwner: TDOMDocument);
661
FOwnerDocument := AOwner;
665
function TDOMNode.GetNodeValue: DOMString;
667
Result := FNodeValue;
670
procedure TDOMNode.SetNodeValue(const AValue: DOMString);
672
FNodeValue := AValue;
675
function TDOMNode.GetChildNodes: TDOMNodeList;
677
Result := TDOMNodeList.Create(Self, '*');
680
function TDOMNode.GetFirstChild: TDOMNode;
685
function TDOMNode.GetLastChild: TDOMNode;
690
function TDOMNode.GetAttributes: TDOMNamedNodeMap;
695
function TDOMNode.InsertBefore(NewChild, RefChild: TDOMNode): TDOMNode;
697
raise EDOMHierarchyRequest.Create('Node.InsertBefore');
698
if (NewChild=nil) and (RefChild=nil) then ;
702
function TDOMNode.ReplaceChild(NewChild, OldChild: TDOMNode): TDOMNode;
704
raise EDOMHierarchyRequest.Create('Node.ReplaceChild');
705
if (NewChild=nil) and (OldChild=nil) then ;
709
function TDOMNode.RemoveChild(OldChild: TDOMNode): TDOMNode;
711
raise EDOMHierarchyRequest.Create('Node.RemoveChild');
712
if (OldChild=nil) then ;
716
function TDOMNode.AppendChild(NewChild: TDOMNode): TDOMNode;
718
raise EDOMHierarchyRequest.Create('Node.AppendChild');
719
if (NewChild=nil) then ;
723
function TDOMNode.HasChildNodes: Boolean;
728
function TDOMNode.CloneNode(deep: Boolean): TDOMNode;
731
Result:=CloneNode(deep, FOwnerDocument);
734
function TDOMNode.IsEmpty: Boolean;
739
function TDOMNode.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
741
raise EDOMNotSupported.Create('CloneNode not implemented for ' + ClassName);
742
if (deep) and (ACloneOwner=nil) then ;
746
function TDOMNode.FindNode(const ANodeName: DOMString): TDOMNode;
751
while Assigned(child) do
753
if child.NodeName = ANodeName then
758
child := child.NextSibling;
763
//------------------------------------------------------------------------------
765
function CompareDOMStrings(const s1, s2: DOMPChar; l1, l2: integer): integer;
770
while (i<l1) and (Result=0) do begin
771
Result:=ord(s1[i])-ord(s2[i]);
776
function CompareDOMNodeWithDOMNode(Node1, Node2: Pointer): integer;
778
Result:=CompareDOMStrings(DOMPChar(Pointer(TDOMNode(Node1).NodeName)),
779
DOMPChar(Pointer(TDOMNode(Node2).NodeName)),
780
length(TDOMNode(Node1).NodeName),
781
length(TDOMNode(Node2).NodeName)
785
function CompareDOMStringWithDOMNode(AKey, ANode: Pointer): integer;
787
Result:=CompareDOMStrings(DOMPChar(AKey),
788
DOMPChar(Pointer(TDOMNode(ANode).NodeName)),
789
length(DOMString(AKey)),
790
length(TDOMNode(ANode).NodeName)
795
function TDOMNode_WithChildren.GetFirstChild: TDOMNode;
797
Result := FFirstChild;
800
function TDOMNode_WithChildren.GetLastChild: TDOMNode;
802
Result := FLastChild;
805
destructor TDOMNode_WithChildren.Destroy;
807
child, next: TDOMNode;
809
if FChildNodeTree<>nil then begin
814
while Assigned(child) do
816
next := child.NextSibling;
823
function TDOMNode_WithChildren.InsertBefore(NewChild, RefChild: TDOMNode):
828
if not Assigned(RefChild) then
830
AppendChild(NewChild);
834
if NewChild.FOwnerDocument <> FOwnerDocument then
835
raise EDOMWrongDocument.Create('NodeWC.InsertBefore');
837
if RefChild.ParentNode <> Self then
838
raise EDOMHierarchyRequest.Create('NodeWC.InsertBefore');
840
if NewChild.NodeType = DOCUMENT_FRAGMENT_NODE then
841
raise EDOMNotSupported.Create('NodeWC.InsertBefore for DocumentFragment');
843
NewChild.FNextSibling := RefChild;
844
if RefChild = FFirstChild then
845
FFirstChild := NewChild
848
RefChild.FPreviousSibling.FNextSibling := NewChild;
849
NewChild.FPreviousSibling := RefChild.FPreviousSibling;
852
RefChild.FPreviousSibling := NewChild;
853
NewChild.FParentNode := Self;
854
AddToChildNodeTree(NewChild);
857
function TDOMNode_WithChildren.ReplaceChild(NewChild, OldChild: TDOMNode):
860
InsertBefore(NewChild, OldChild);
861
if Assigned(OldChild) then
862
RemoveChild(OldChild);
866
function TDOMNode_WithChildren.RemoveChild(OldChild: TDOMNode):
869
if OldChild.ParentNode <> Self then
870
raise EDOMHierarchyRequest.Create('NodeWC.RemoveChild');
872
if OldChild = FFirstChild then
873
FFirstChild := FFirstChild.NextSibling
875
OldChild.FPreviousSibling.FNextSibling := OldChild.FNextSibling;
877
if OldChild = FLastChild then
878
FLastChild := FLastChild.FPreviousSibling
880
OldChild.FNextSibling.FPreviousSibling := OldChild.FPreviousSibling;
882
RemoveFromChildNodeTree(OldChild);
887
function TDOMNode_WithChildren.AppendChild(NewChild: TDOMNode): TDOMNode;
891
//writeln('TDOMNode_WithChildren.AppendChild ',NodeName,' NewChild=',NewChild.NodeName);
892
if NewChild.FOwnerDocument <> FOwnerDocument then
893
raise EDOMWrongDocument.Create('NodeWC.AppendChild');
896
while Assigned(Parent) do
898
if Parent = NewChild then
899
raise EDOMHierarchyRequest.Create('NodeWC.AppendChild (cycle in tree)');
900
Parent := Parent.ParentNode;
903
if NewChild.FParentNode<>nil then begin
904
//writeln('TDOMNode_WithChildren.AppendChild old NewChild.FParentNode=',NewChild.FParentNode.NodeName);
905
NewChild.FParentNode.RemoveChild(NewChild);
908
if NewChild.NodeType = DOCUMENT_FRAGMENT_NODE then
909
raise EDOMNotSupported.Create('NodeWC.AppendChild for DocumentFragments')
911
if Assigned(FFirstChild) then
913
FLastChild.FNextSibling := NewChild;
914
NewChild.FPreviousSibling := FLastChild;
916
FFirstChild := NewChild;
917
FLastChild := NewChild;
918
NewChild.FParentNode := Self;
920
AddToChildNodeTree(NewChild);
924
function TDOMNode_WithChildren.HasChildNodes: Boolean;
926
Result := Assigned(FFirstChild);
929
function TDOMNode_WithChildren.FindNode(const ANodeName: DOMString): TDOMNode;
931
AVLNode: TAVLTreeNode;
934
if FChildNodeTree<>nil then begin
935
// use tree for fast search
936
//if FChildNodeTree.ConsistencyCheck<>0 then
937
// raise exception.Create('TDOMNode_WithChildren.FindNode');
938
AVLNode:=FChildNodeTree.FindKey(DOMPChar(Pointer(ANodeName)),
939
@CompareDOMStringWithDOMNode);
941
Result:=TDOMNode(AVLNode.Data);
944
Result := FirstChild;
945
while Assigned(Result) do begin
946
if CompareDOMStringWithDOMNode(DOMPChar(Pointer(ANodeName)),Result)=0
948
Result := Result.NextSibling;
953
procedure TDOMNode_WithChildren.CloneChildren(ACopy: TDOMNode;
954
ACloneOwner: TDOMDocument);
959
while Assigned(node) do
961
ACopy.AppendChild(node.CloneNode(True, ACloneOwner));
962
node := node.NextSibling;
966
procedure TDOMNode_WithChildren.AddToChildNodeTree(NewNode: TDOMNode);
970
NewNodeAdded: Boolean;
972
if (FChildNodeTree=nil) then begin
973
// there is no childnodetree yet
974
// Most xml trees contains nodes with only a few child nodes. It would be
975
// overhead to create a tree for only a few children.
978
while Assigned(ANode) do begin
980
ANode := ANode.NextSibling;
982
if ChildCount>5 then begin
983
FChildNodeTree:=TAVLTree.Create(@CompareDOMNodeWithDOMNode);
984
// add all existing children
987
while Assigned(ANode) do begin
988
if ANode=NewNode then NewNodeAdded:=true;
989
FChildNodeTree.Add(ANode);
990
ANode := ANode.NextSibling;
992
if not NewNodeAdded then
993
FChildNodeTree.Add(NewNode);
996
{if (FChildNodeTree.Find(NewNode)<>nil) then begin
997
writeln('TDOMNode_WithChildren.AddToChildNodeTree adding same value ',NewNOde.NodeName);
1000
FChildNodeTree.Add(NewNode);
1002
//if FChildNodeTree.ConsistencyCheck<>0 then
1003
// raise exception.Create('TDOMNode_WithChildren.FindNode');
1006
procedure TDOMNode_WithChildren.RemoveFromChildNodeTree(OldNode: TDOMNode);
1008
if FChildNodeTree<>nil then
1009
FChildNodeTree.RemovePointer(OldNode);// doubles are allowed, so Remove can not be used
1010
//if (FChildNodeTree<>nil) and (FChildNodeTree.ConsistencyCheck<>0) then
1011
// raise exception.Create('TDOMNode_WithChildren.FindNode');
1015
// -------------------------------------------------------
1017
// -------------------------------------------------------
1019
constructor TDOMNodeList.Create(ANode: TDOMNode; const AFilter: DOMString);
1024
UseFilter := filter <> '*';
1027
function TDOMNodeList.GetCount: LongInt;
1032
child := node.FirstChild;
1033
while Assigned(child) do
1035
if (not UseFilter) or (child.NodeName = filter) then
1037
child := child.NextSibling;
1041
function TDOMNodeList.GetItem(index: LongWord): TDOMNode;
1046
child := node.FirstChild;
1047
while Assigned(child) do
1054
if (not UseFilter) or (child.NodeName = filter) then
1056
child := child.NextSibling;
1061
// -------------------------------------------------------
1063
// -------------------------------------------------------
1065
constructor TDOMNamedNodeMap.Create(AOwner: TDOMDocument);
1068
OwnerDocument := AOwner;
1071
function TDOMNamedNodeMap.GetItem(index: LongWord): TDOMNode;
1073
Result := TDOMNode(Items[index]);
1076
procedure TDOMNamedNodeMap.SetItem(index: LongWord; AItem: TDOMNode);
1078
Items[index] := AItem;
1081
function TDOMNamedNodeMap.GetLength: LongInt;
1086
function TDOMNamedNodeMap.GetNamedItem(const name: DOMString): TDOMNode;
1090
for i := 0 to Count - 1 do
1093
if Result.NodeName = name then
1099
function TDOMNamedNodeMap.SetNamedItem(arg: TDOMNode): TDOMNode;
1103
if arg.FOwnerDocument <> OwnerDocument then
1104
raise EDOMWrongDocument.Create('NamedNodeMap.SetNamedItem');
1106
if arg.NodeType = ATTRIBUTE_NODE then
1108
if Assigned(TDOMAttr(arg).AttrOwner) then
1109
raise EDOMInUseAttribute.Create('NamedNodeMap.SetNamedItem');
1110
TDOMAttr(arg).AttrOwner := Self;
1113
for i := 0 to Count - 1 do
1114
if Item[i].NodeName = arg.NodeName then
1124
function TDOMNamedNodeMap.RemoveNamedItem(const name: DOMString): TDOMNode;
1128
for i := 0 to Count - 1 do
1129
if Item[i].NodeName = name then
1132
Result.FParentNode := nil;
1135
raise EDOMNotFound.Create('NamedNodeMap.RemoveNamedItem');
1139
// -------------------------------------------------------
1141
// -------------------------------------------------------
1143
function TDOMCharacterData.GetLength: LongInt;
1145
Result := system.Length(FNodeValue);
1148
function TDOMCharacterData.SubstringData(offset, count: LongWord): DOMString;
1150
if (offset < 0) or (longint(offset) > Length) or (count < 0) then
1151
raise EDOMIndexSize.Create('CharacterData.SubstringData');
1152
Result := Copy(FNodeValue, offset + 1, count);
1155
procedure TDOMCharacterData.AppendData(const arg: DOMString);
1157
FNodeValue := FNodeValue + arg;
1160
procedure TDOMCharacterData.InsertData(offset: LongWord; const arg: DOMString);
1162
if (offset < 0) or (longint(offset) > Length) then
1163
raise EDOMIndexSize.Create('CharacterData.InsertData');
1165
FNodeValue := Copy(FNodeValue, 1, offset) + arg +
1166
Copy(FNodeValue, offset + 1, Length);
1169
procedure TDOMCharacterData.DeleteData(offset, count: LongWord);
1171
if (offset < 0) or (longint(offset) > Length) or (count < 0) then
1172
raise EDOMIndexSize.Create('CharacterData.DeleteData');
1174
FNodeValue := Copy(FNodeValue, 1, offset) +
1175
Copy(FNodeValue, offset + count + 1, Length);
1178
procedure TDOMCharacterData.ReplaceData(offset, count: LongWord; const arg: DOMString);
1180
DeleteData(offset, count);
1181
InsertData(offset, arg);
1185
// -------------------------------------------------------
1187
// -------------------------------------------------------
1189
constructor TDOMDocumentFragment.Create(AOwner: TDOMDocument);
1191
FNodeType := DOCUMENT_FRAGMENT_NODE;
1192
FNodeName := '#document-fragment';
1193
inherited Create(AOwner);
1197
// -------------------------------------------------------
1198
// DOMImplementation
1199
// -------------------------------------------------------
1201
function TDOMImplementation.HasFeature(const feature, version: DOMString):
1205
if (feature='') and (version='') then ;
1208
function TDOMImplementation.CreateDocumentType(const QualifiedName, PublicID,
1209
SystemID: DOMString): TDOMDocumentType;
1211
// !!!: Implement this method (easy to do)
1212
raise EDOMNotSupported.Create('DOMImplementation.CreateDocumentType');
1213
if (QualifiedName='') and (PublicID='') and (SystemID='') then ;
1217
function TDOMImplementation.CreateDocument(const NamespaceURI,
1218
QualifiedName: DOMString; doctype: TDOMDocumentType): TDOMDocument;
1220
// !!!: Implement this method (easy to do)
1221
raise EDOMNotSupported.Create('DOMImplementation.CreateDocument');
1222
if (NamespaceURI='') and (QualifiedName='') and (doctype=nil) then ;
1227
// -------------------------------------------------------
1229
// -------------------------------------------------------
1231
constructor TDOMDocument.Create;
1233
FNodeType := DOCUMENT_NODE;
1234
FNodeName := '#document';
1235
inherited Create(nil);
1236
FOwnerDocument := Self;
1239
function TDOMDocument.GetDocumentElement: TDOMElement;
1243
node := FFirstChild;
1244
while Assigned(node) do
1246
if node.FNodeType = ELEMENT_NODE then
1248
Result := TDOMElement(node);
1251
node := node.NextSibling;
1256
function TDOMDocument.CreateElement(const tagName: DOMString): TDOMElement;
1258
Result := TDOMElement.Create(Self);
1259
Result.FNodeName := tagName;
1262
function TDOMDocument.CreateDocumentFragment: TDOMDocumentFragment;
1264
Result := TDOMDocumentFragment.Create(Self);
1267
function TDOMDocument.CreateTextNode(const data: DOMString): TDOMText;
1269
Result := TDOMText.Create(Self);
1270
Result.FNodeValue := data;
1273
function TDOMDocument.CreateComment(const data: DOMString): TDOMComment;
1275
Result := TDOMComment.Create(Self);
1276
Result.FNodeValue := data;
1279
function TDOMDocument.CreateCDATASection(const data: DOMString):
1282
raise EDOMNotSupported.Create('DOMDocument.CreateCDATASection');
1287
function TDOMDocument.CreateProcessingInstruction(const target,
1288
data: DOMString): TDOMProcessingInstruction;
1290
raise EDOMNotSupported.Create('DOMDocument.CreateProcessingInstruction');
1291
if (target='') and (data='') then ;
1295
function TDOMDocument.CreateAttribute(const name: DOMString): TDOMAttr;
1297
Result := TDOMAttr.Create(Self);
1298
Result.FNodeName := name;
1301
function TDOMDocument.CreateEntityReference(const name: DOMString):
1302
TDOMEntityReference;
1304
raise EDOMNotSupported.Create('DOMDocument.CreateEntityReference');
1309
function TDOMDocument.CreateEntity(const data: DOMString): TDOMEntity;
1311
Result := TDOMEntity.Create(Self);
1312
Result.FNodeName := data;
1315
function TDOMDocument.GetElementsByTagName(const tagname: DOMString): TDOMNodeList;
1317
Result := TDOMNodeList.Create(Self, tagname);
1321
function TXMLDocument.CreateCDATASection(const data: DOMString):
1324
Result := TDOMCDATASection.Create(Self);
1325
Result.FNodeValue := data;
1328
function TXMLDocument.CreateProcessingInstruction(const target,
1329
data: DOMString): TDOMProcessingInstruction;
1331
Result := TDOMProcessingInstruction.Create(Self);
1332
Result.FNodeName := target;
1333
Result.FNodeValue := data;
1336
function TXMLDocument.CreateEntityReference(const name: DOMString):
1337
TDOMEntityReference;
1339
Result := TDOMEntityReference.Create(Self);
1340
Result.FNodeName := name;
1344
// -------------------------------------------------------
1346
// -------------------------------------------------------
1348
constructor TDOMAttr.Create(AOwner: TDOMDocument);
1350
FNodeType := ATTRIBUTE_NODE;
1351
inherited Create(AOwner);
1354
function TDOMAttr.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
1356
Result := TDOMAttr.Create(ACloneOwner);
1357
Result.FNodeName := FNodeName;
1358
TDOMAttr(Result).FSpecified := FSpecified;
1360
CloneChildren(Result, ACloneOwner);
1363
function TDOMAttr.GetNodeValue: DOMString;
1367
SetLength(Result, 0);
1368
if Assigned(FFirstChild) then
1370
child := FFirstChild;
1371
while Assigned(child) do
1373
if child.NodeType = ENTITY_REFERENCE_NODE then
1374
Result := Result + '&' + child.NodeName + ';'
1376
Result := Result + child.NodeValue;
1377
child := child.NextSibling;
1382
procedure TDOMAttr.SetNodeValue(const AValue: DOMString);
1387
tn := TDOMText.Create(FOwnerDocument);
1388
tn.FNodeValue := AValue;
1389
if Assigned(FFirstChild) then
1390
ReplaceChild(tn, FFirstChild)
1396
// -------------------------------------------------------
1398
// -------------------------------------------------------
1400
constructor TDOMElement.Create(AOwner: TDOMDocument);
1402
FNodeType := ELEMENT_NODE;
1403
inherited Create(AOwner);
1406
destructor TDOMElement.Destroy;
1410
{As the attributes are _not_ children of the element node, we have to free
1411
them manually here:}
1412
if FAttributes<>nil then begin
1413
for i := 0 to FAttributes.Count - 1 do
1414
FAttributes[i].Free;
1421
function TDOMElement.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
1425
Result := TDOMElement.Create(ACloneOwner);
1426
Result.FNodeName := FNodeName;
1427
if FAttributes<>nil then begin
1428
TDOMElement(Result).GetAttributes;
1429
for i := 0 to FAttributes.Count - 1 do
1430
TDOMElement(Result).FAttributes.Add(FAttributes[i].CloneNode(True, ACloneOwner));
1433
CloneChildren(Result, ACloneOwner);
1436
function TDOMElement.GetAttributes: TDOMNamedNodeMap;
1438
if FAttributes=nil then
1439
FAttributes := TDOMNamedNodeMap.Create(FOwnerDocument);
1440
Result := FAttributes;
1443
function TDOMElement.GetAttribute(const name: DOMString): DOMString;
1447
if FAttributes<>nil then begin
1448
for i := 0 to FAttributes.Count - 1 do
1449
if FAttributes[i].NodeName = name then
1451
Result := FAttributes[i].NodeValue;
1455
SetLength(Result, 0);
1458
procedure TDOMElement.SetAttribute(const name, value: DOMString);
1464
for i := 0 to FAttributes.Count - 1 do
1465
if FAttributes[i].NodeName = name then
1467
FAttributes[i].NodeValue := value;
1470
attr := TDOMAttr.Create(FOwnerDocument);
1471
attr.FNodeName := name;
1472
attr.NodeValue := value;
1473
FAttributes.Add(attr);
1476
procedure TDOMElement.RemoveAttribute(const name: DOMString);
1480
if FAttributes=nil then exit;
1481
for i := 0 to FAttributes.Count - 1 do
1482
if FAttributes[i].NodeName = name then
1484
FAttributes[i].Free;
1485
FAttributes.Delete(i);
1490
function TDOMElement.GetAttributeNode(const name: DOMString): TDOMAttr;
1494
if FAttributes<>nil then begin
1495
for i := 0 to FAttributes.Count - 1 do
1496
if FAttributes[i].NodeName = name then
1498
Result := TDOMAttr(FAttributes[i]);
1505
procedure TDOMElement.SetAttributeNode(NewAttr: TDOMAttr);
1509
if FAttributes=nil then exit;
1510
for i := 0 to FAttributes.Count - 1 do
1511
if FAttributes[i].NodeName = NewAttr.NodeName then
1513
FAttributes[i].Free;
1514
FAttributes[i] := NewAttr;
1519
function TDOMElement.RemoveAttributeNode(OldAttr: TDOMAttr): TDOMAttr;
1525
if FAttributes=nil then exit;
1526
for i := 0 to FAttributes.Count - 1 do
1528
node := FAttributes[i];
1529
if node = OldAttr then
1531
FAttributes.Delete(i);
1532
Result := TDOMAttr(node);
1538
function TDOMElement.GetElementsByTagName(const name: DOMString): TDOMNodeList;
1540
Result := TDOMNodeList.Create(Self, name);
1543
function TDOMElement.IsEmpty: Boolean;
1545
Result:=(FAttributes=nil) or (FAttributes.Count=0)
1548
procedure TDOMElement.Normalize;
1550
// !!!: Not implemented
1554
// -------------------------------------------------------
1556
// -------------------------------------------------------
1558
constructor TDOMText.Create(AOwner: TDOMDocument);
1560
FNodeType := TEXT_NODE;
1561
FNodeName := '#text';
1562
inherited Create(AOwner);
1565
function TDOMText.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
1567
Result := TDOMText.Create(ACloneOwner);
1568
Result.FNodeValue := FNodeValue;
1569
if deep and (ACloneOwner=nil) then ;
1572
function TDOMText.SplitText(offset: LongWord): TDOMText;
1574
if longint(offset) > Length then
1575
raise EDOMIndexSize.Create('Text.SplitText');
1577
Result := TDOMText.Create(FOwnerDocument);
1578
Result.FNodeValue := Copy(FNodeValue, offset + 1, Length);
1579
FNodeValue := Copy(FNodeValue, 1, offset);
1580
FParentNode.InsertBefore(Result, FNextSibling);
1584
// -------------------------------------------------------
1586
// -------------------------------------------------------
1588
constructor TDOMComment.Create(AOwner: TDOMDocument);
1590
FNodeType := COMMENT_NODE;
1591
FNodeName := '#comment';
1592
inherited Create(AOwner);
1595
function TDOMComment.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
1597
Result := TDOMComment.Create(ACloneOwner);
1598
Result.FNodeValue := FNodeValue;
1599
if deep and (ACloneOwner=nil) then ;
1603
// -------------------------------------------------------
1605
// -------------------------------------------------------
1607
constructor TDOMCDATASection.Create(AOwner: TDOMDocument);
1609
inherited Create(AOwner);
1610
FNodeType := CDATA_SECTION_NODE;
1611
FNodeName := '#cdata-section';
1614
function TDOMCDATASection.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
1616
Result := TDOMCDATASection.Create(ACloneOwner);
1617
Result.FNodeValue := FNodeValue;
1618
if deep and (ACloneOwner=nil) then ;
1622
// -------------------------------------------------------
1624
// -------------------------------------------------------
1626
constructor TDOMDocumentType.Create(AOwner: TDOMDocument);
1628
FNodeType := DOCUMENT_TYPE_NODE;
1629
inherited Create(AOwner);
1632
function TDOMDocumentType.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
1634
Result := TDOMDocumentType.Create(ACloneOwner);
1635
Result.FNodeName := FNodeName;
1636
if deep and (ACloneOwner=nil) then ;
1640
// -------------------------------------------------------
1642
// -------------------------------------------------------
1644
constructor TDOMNotation.Create(AOwner: TDOMDocument);
1646
FNodeType := NOTATION_NODE;
1647
inherited Create(AOwner);
1650
function TDOMNotation.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
1652
Result := TDOMNotation.Create(ACloneOwner);
1653
Result.FNodeName := FNodeName;
1654
if deep and (ACloneOwner=nil) then ;
1658
// -------------------------------------------------------
1660
// -------------------------------------------------------
1662
constructor TDOMEntity.Create(AOwner: TDOMDocument);
1664
FNodeType := ENTITY_NODE;
1665
inherited Create(AOwner);
1669
// -------------------------------------------------------
1671
// -------------------------------------------------------
1673
constructor TDOMEntityReference.Create(AOwner: TDOMDocument);
1675
FNodeType := ENTITY_REFERENCE_NODE;
1676
inherited Create(AOwner);
1680
// -------------------------------------------------------
1681
// ProcessingInstruction
1682
// -------------------------------------------------------
1684
constructor TDOMProcessingInstruction.Create(AOwner: TDOMDocument);
1686
FNodeType := PROCESSING_INSTRUCTION_NODE;
1687
inherited Create(AOwner);