dom.pp 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640
  1. {
  2. This file is part of the Free Component Library
  3. Implementation of DOM interfaces
  4. Copyright (c) 1999-2000 by Sebastian Guenther, [email protected]
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {
  12. This unit provides classes which implement the interfaces defined in the
  13. DOM (Document Object Model) specification.
  14. The current state is:
  15. DOM Level 1 - Almost completely implemented
  16. DOM Level 2 - Partially implemented
  17. Specification used for this implementation:
  18. "Document Object Model (DOM) Level 2 Specification Version 1.0
  19. W3C Candidate Recommendation 07 March, 2000"
  20. http://www.w3.org/TR/2000/CR-DOM-Level-2-20000307
  21. }
  22. unit DOM;
  23. {$MODE objfpc}
  24. {$H+}
  25. interface
  26. {off $DEFINE MEM_CHECK}
  27. uses
  28. {$IFDEF MEM_CHECK}MemCheck,{$ENDIF}
  29. SysUtils, Classes, AVL_Tree;
  30. type
  31. TDOMImplementation = class;
  32. TDOMDocumentFragment = class;
  33. TDOMDocument = class;
  34. TDOMNode = class;
  35. TDOMNodeList = class;
  36. TDOMNamedNodeMap = class;
  37. TDOMCharacterData = class;
  38. TDOMAttr = class;
  39. TDOMElement = class;
  40. TDOMText = class;
  41. TDOMComment = class;
  42. TDOMCDATASection = class;
  43. TDOMDocumentType = class;
  44. TDOMNotation = class;
  45. TDOMEntity = class;
  46. TDOMEntityReference = class;
  47. TDOMProcessingInstruction = class;
  48. // -------------------------------------------------------
  49. // DOMString
  50. // -------------------------------------------------------
  51. DOMString = WideString;
  52. DOMPChar = PWideChar;
  53. // -------------------------------------------------------
  54. // DOMException
  55. // -------------------------------------------------------
  56. const
  57. // DOM Level 1 exception codes:
  58. INDEX_SIZE_ERR = 1; // index or size is negative, or greater than the allowed value
  59. DOMSTRING_SIZE_ERR = 2; // Specified range of text does not fit into a DOMString
  60. HIERARCHY_REQUEST_ERR = 3; // node is inserted somewhere it does not belong
  61. WRONG_DOCUMENT_ERR = 4; // node is used in a different document than the one that created it (that does not support it)
  62. INVALID_CHARACTER_ERR = 5; // invalid or illegal character is specified, such as in a name
  63. NO_DATA_ALLOWED_ERR = 6; // data is specified for a node which does not support data
  64. NO_MODIFICATION_ALLOWED_ERR = 7; // an attempt is made to modify an object where modifications are not allowed
  65. NOT_FOUND_ERR = 8; // an attempt is made to reference a node in a context where it does not exist
  66. NOT_SUPPORTED_ERR = 9; // implementation does not support the type of object requested
  67. INUSE_ATTRIBUTE_ERR = 10; // an attempt is made to add an attribute that is already in use elsewhere
  68. // DOM Level 2 exception codes:
  69. INVALID_STATE_ERR = 11; // an attempt is made to use an object that is not, or is no longer, usable
  70. SYNTAX_ERR = 12; // invalid or illegal string specified
  71. INVALID_MODIFICATION_ERR = 13; // an attempt is made to modify the type of the underlying object
  72. NAMESPACE_ERR = 14; // an attempt is made to create or change an object in a way which is incorrect with regard to namespaces
  73. INVALID_ACCESS_ERR = 15; // parameter or operation is not supported by the underlying object
  74. type
  75. EDOMError = class(Exception)
  76. public
  77. constructor Create(ACode: Integer; const ASituation: String);
  78. Code: Integer;
  79. end;
  80. EDOMIndexSize = class(EDOMError)
  81. public
  82. constructor Create(const ASituation: String);
  83. end;
  84. EDOMHierarchyRequest = class(EDOMError)
  85. public
  86. constructor Create(const ASituation: String);
  87. end;
  88. EDOMWrongDocument = class(EDOMError)
  89. public
  90. constructor Create(const ASituation: String);
  91. end;
  92. EDOMNotFound = class(EDOMError)
  93. public
  94. constructor Create(const ASituation: String);
  95. end;
  96. EDOMNotSupported = class(EDOMError)
  97. public
  98. constructor Create(const ASituation: String);
  99. end;
  100. EDOMInUseAttribute = class(EDOMError)
  101. public
  102. constructor Create(const ASituation: String);
  103. end;
  104. EDOMInvalidState = class(EDOMError)
  105. public
  106. constructor Create(const ASituation: String);
  107. end;
  108. EDOMSyntax = class(EDOMError)
  109. public
  110. constructor Create(const ASituation: String);
  111. end;
  112. EDOMInvalidModification = class(EDOMError)
  113. public
  114. constructor Create(const ASituation: String);
  115. end;
  116. EDOMNamespace = class(EDOMError)
  117. public
  118. constructor Create(const ASituation: String);
  119. end;
  120. EDOMInvalidAccess = class(EDOMError)
  121. public
  122. constructor Create(const ASituation: String);
  123. end;
  124. // -------------------------------------------------------
  125. // Node
  126. // -------------------------------------------------------
  127. const
  128. ELEMENT_NODE = 1;
  129. ATTRIBUTE_NODE = 2;
  130. TEXT_NODE = 3;
  131. CDATA_SECTION_NODE = 4;
  132. ENTITY_REFERENCE_NODE = 5;
  133. ENTITY_NODE = 6;
  134. PROCESSING_INSTRUCTION_NODE = 7;
  135. COMMENT_NODE = 8;
  136. DOCUMENT_NODE = 9;
  137. DOCUMENT_TYPE_NODE = 10;
  138. DOCUMENT_FRAGMENT_NODE = 11;
  139. NOTATION_NODE = 12;
  140. type
  141. TRefClass = class
  142. protected
  143. RefCounter: LongInt;
  144. public
  145. constructor Create;
  146. function AddRef: LongInt; virtual;
  147. function Release: LongInt; virtual;
  148. end;
  149. TDOMNode = class
  150. protected
  151. FNodeName, FNodeValue: DOMString;
  152. FNodeType: Integer;
  153. FParentNode: TDOMNode;
  154. FPreviousSibling, FNextSibling: TDOMNode;
  155. FOwnerDocument: TDOMDocument;
  156. function GetNodeValue: DOMString; virtual;
  157. procedure SetNodeValue(const AValue: DOMString); virtual;
  158. function GetFirstChild: TDOMNode; virtual;
  159. function GetLastChild: TDOMNode; virtual;
  160. function GetAttributes: TDOMNamedNodeMap; virtual;
  161. public
  162. constructor Create(AOwner: TDOMDocument);
  163. // Free NodeList with TDOMNodeList.Release!
  164. function GetChildNodes: TDOMNodeList; virtual;
  165. property NodeName: DOMString read FNodeName;
  166. property NodeValue: DOMString read GetNodeValue write SetNodeValue;
  167. property NodeType: Integer read FNodeType;
  168. property ParentNode: TDOMNode read FParentNode;
  169. property FirstChild: TDOMNode read GetFirstChild;
  170. property LastChild: TDOMNode read GetLastChild;
  171. property ChildNodes: TDOMNodeList read GetChildNodes;
  172. property PreviousSibling: TDOMNode read FPreviousSibling;
  173. property NextSibling: TDOMNode read FNextSibling;
  174. property Attributes: TDOMNamedNodeMap read GetAttributes;
  175. property OwnerDocument: TDOMDocument read FOwnerDocument;
  176. function InsertBefore(NewChild, RefChild: TDOMNode): TDOMNode; virtual;
  177. function ReplaceChild(NewChild, OldChild: TDOMNode): TDOMNode; virtual;
  178. function RemoveChild(OldChild: TDOMNode): TDOMNode; virtual;
  179. function AppendChild(NewChild: TDOMNode): TDOMNode; virtual;
  180. function HasChildNodes: Boolean; virtual;
  181. function CloneNode(deep: Boolean): TDOMNode; overload;
  182. // Extensions to DOM interface:
  183. function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; virtual;
  184. function FindNode(const ANodeName: DOMString): TDOMNode; virtual;
  185. end;
  186. { The following class is an implementation specific extension, it is just an
  187. extended implementation of TDOMNode, the generic DOM::Node interface
  188. implementation. (Its main purpose is to save memory in a big node tree) }
  189. TDOMNode_WithChildren = class(TDOMNode)
  190. protected
  191. FFirstChild, FLastChild: TDOMNode;
  192. FChildNodeTree: TAVLTree;
  193. function GetFirstChild: TDOMNode; override;
  194. function GetLastChild: TDOMNode; override;
  195. procedure CloneChildren(ACopy: TDOMNode; ACloneOwner: TDOMDocument);
  196. procedure AddToChildNodeTree(NewNode: TDOMNode);
  197. procedure RemoveFromChildNodeTree(OldNode: TDOMNode);
  198. public
  199. destructor Destroy; override;
  200. function InsertBefore(NewChild, RefChild: TDOMNode): TDOMNode; override;
  201. function ReplaceChild(NewChild, OldChild: TDOMNode): TDOMNode; override;
  202. function RemoveChild(OldChild: TDOMNode): TDOMNode; override;
  203. function AppendChild(NewChild: TDOMNode): TDOMNode; override;
  204. function HasChildNodes: Boolean; override;
  205. function FindNode(const ANodeName: DOMString): TDOMNode; override;
  206. end;
  207. // -------------------------------------------------------
  208. // NodeList
  209. // -------------------------------------------------------
  210. TDOMNodeList = class(TRefClass)
  211. protected
  212. node: TDOMNode;
  213. filter: DOMString;
  214. UseFilter: Boolean;
  215. function GetCount: LongWord;
  216. function GetItem(index: LongWord): TDOMNode;
  217. public
  218. constructor Create(ANode: TDOMNode; const AFilter: DOMString);
  219. property Item[index: LongWord]: TDOMNode read GetItem;
  220. property Count: LongWord read GetCount;
  221. end;
  222. // -------------------------------------------------------
  223. // NamedNodeMap
  224. // -------------------------------------------------------
  225. TDOMNamedNodeMap = class(TList)
  226. protected
  227. OwnerDocument: TDOMDocument;
  228. function GetItem(index: LongWord): TDOMNode;
  229. procedure SetItem(index: LongWord; AItem: TDOMNode);
  230. function GetLength: LongWord;
  231. public
  232. constructor Create(AOwner: TDOMDocument);
  233. function GetNamedItem(const name: DOMString): TDOMNode;
  234. function SetNamedItem(arg: TDOMNode): TDOMNode;
  235. function RemoveNamedItem(const name: DOMString): TDOMNode;
  236. property Item[index: LongWord]: TDOMNode read GetItem write SetItem; default;
  237. property Length: LongWord read GetLength;
  238. end;
  239. // -------------------------------------------------------
  240. // CharacterData
  241. // -------------------------------------------------------
  242. TDOMCharacterData = class(TDOMNode)
  243. protected
  244. function GetLength: LongWord;
  245. public
  246. property Data: DOMString read FNodeValue;
  247. property Length: LongWord read GetLength;
  248. function SubstringData(offset, count: LongWord): DOMString;
  249. procedure AppendData(const arg: DOMString);
  250. procedure InsertData(offset: LongWord; const arg: DOMString);
  251. procedure DeleteData(offset, count: LongWord);
  252. procedure ReplaceData(offset, count: LongWord; const arg: DOMString);
  253. end;
  254. // -------------------------------------------------------
  255. // DOMImplementation
  256. // -------------------------------------------------------
  257. TDOMImplementation = class
  258. public
  259. function HasFeature(const feature, version: DOMString): Boolean;
  260. // Introduced in DOM Level 2:
  261. function CreateDocumentType(const QualifiedName, PublicID,
  262. SystemID: DOMString): TDOMDocumentType;
  263. function CreateDocument(const NamespaceURI, QualifiedName: DOMString;
  264. doctype: TDOMDocumentType): TDOMDocument;
  265. end;
  266. // -------------------------------------------------------
  267. // DocumentFragment
  268. // -------------------------------------------------------
  269. TDOMDocumentFragment = class(TDOMNode_WithChildren)
  270. public
  271. constructor Create(AOwner: TDOMDocument);
  272. end;
  273. // -------------------------------------------------------
  274. // Document
  275. // -------------------------------------------------------
  276. TDOMDocument = class(TDOMNode_WithChildren)
  277. protected
  278. FDocType: TDOMDocumentType;
  279. FImplementation: TDOMImplementation;
  280. function GetDocumentElement: TDOMElement;
  281. public
  282. property DocType: TDOMDocumentType read FDocType;
  283. property Impl: TDOMImplementation read FImplementation;
  284. property DocumentElement: TDOMElement read GetDocumentElement;
  285. function CreateElement(const tagName: DOMString): TDOMElement; virtual;
  286. function CreateDocumentFragment: TDOMDocumentFragment;
  287. function CreateTextNode(const data: DOMString): TDOMText;
  288. function CreateComment(const data: DOMString): TDOMComment;
  289. function CreateCDATASection(const data: DOMString): TDOMCDATASection;
  290. virtual;
  291. function CreateProcessingInstruction(const target, data: DOMString):
  292. TDOMProcessingInstruction; virtual;
  293. function CreateAttribute(const name: DOMString): TDOMAttr; virtual;
  294. function CreateEntityReference(const name: DOMString): TDOMEntityReference;
  295. virtual;
  296. // Free NodeList with TDOMNodeList.Release!
  297. function GetElementsByTagName(const tagname: DOMString): TDOMNodeList;
  298. // Extensions to DOM interface:
  299. constructor Create;
  300. function CreateEntity(const data: DOMString): TDOMEntity;
  301. end;
  302. TXMLDocument = class(TDOMDocument)
  303. public
  304. // These fields are extensions to the DOM interface:
  305. XMLVersion, Encoding, StylesheetType, StylesheetHRef: DOMString;
  306. function CreateCDATASection(const data: DOMString): TDOMCDATASection; override;
  307. function CreateProcessingInstruction(const target, data: DOMString):
  308. TDOMProcessingInstruction; override;
  309. function CreateEntityReference(const name: DOMString): TDOMEntityReference; override;
  310. end;
  311. // -------------------------------------------------------
  312. // Attr
  313. // -------------------------------------------------------
  314. TDOMAttr = class(TDOMNode_WithChildren)
  315. protected
  316. FSpecified: Boolean;
  317. AttrOwner: TDOMNamedNodeMap;
  318. function GetNodeValue: DOMString; override;
  319. procedure SetNodeValue(const AValue: DOMString); override;
  320. public
  321. constructor Create(AOwner: TDOMDocument);
  322. function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
  323. property Name: DOMString read FNodeName;
  324. property Specified: Boolean read FSpecified;
  325. property Value: DOMString read GetNodeValue write SetNodeValue;
  326. end;
  327. // -------------------------------------------------------
  328. // Element
  329. // -------------------------------------------------------
  330. TDOMElement = class(TDOMNode_WithChildren)
  331. private
  332. FAttributes: TDOMNamedNodeMap;
  333. protected
  334. function GetAttributes: TDOMNamedNodeMap; override;
  335. public
  336. constructor Create(AOwner: TDOMDocument);
  337. destructor Destroy; override;
  338. function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
  339. property TagName: DOMString read FNodeName;
  340. function GetAttribute(const name: DOMString): DOMString;
  341. procedure SetAttribute(const name, value: DOMString);
  342. procedure RemoveAttribute(const name: DOMString);
  343. function GetAttributeNode(const name: DOMString): TDOMAttr;
  344. procedure SetAttributeNode(NewAttr: TDOMAttr);
  345. function RemoveAttributeNode(OldAttr: TDOMAttr): TDOMAttr;
  346. // Free NodeList with TDOMNodeList.Release!
  347. function GetElementsByTagName(const name: DOMString): TDOMNodeList;
  348. procedure Normalize;
  349. property AttribStrings[const Name: DOMString]: DOMString
  350. read GetAttribute write SetAttribute; default;
  351. end;
  352. // -------------------------------------------------------
  353. // Text
  354. // -------------------------------------------------------
  355. TDOMText = class(TDOMCharacterData)
  356. public
  357. constructor Create(AOwner: TDOMDocument);
  358. function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
  359. function SplitText(offset: LongWord): TDOMText;
  360. end;
  361. // -------------------------------------------------------
  362. // Comment
  363. // -------------------------------------------------------
  364. TDOMComment = class(TDOMCharacterData)
  365. public
  366. constructor Create(AOwner: TDOMDocument);
  367. function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
  368. end;
  369. // -------------------------------------------------------
  370. // CDATASection
  371. // -------------------------------------------------------
  372. TDOMCDATASection = class(TDOMText)
  373. public
  374. constructor Create(AOwner: TDOMDocument);
  375. function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
  376. end;
  377. // -------------------------------------------------------
  378. // DocumentType
  379. // -------------------------------------------------------
  380. TDOMDocumentType = class(TDOMNode)
  381. protected
  382. FEntities, FNotations: TDOMNamedNodeMap;
  383. public
  384. constructor Create(AOwner: TDOMDocument);
  385. function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
  386. property Name: DOMString read FNodeName;
  387. property Entities: TDOMNamedNodeMap read FEntities;
  388. property Notations: TDOMNamedNodeMap read FEntities;
  389. end;
  390. // -------------------------------------------------------
  391. // Notation
  392. // -------------------------------------------------------
  393. TDOMNotation = class(TDOMNode)
  394. protected
  395. FPublicID, FSystemID: DOMString;
  396. public
  397. constructor Create(AOwner: TDOMDocument);
  398. function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
  399. property PublicID: DOMString read FPublicID;
  400. property SystemID: DOMString read FSystemID;
  401. end;
  402. // -------------------------------------------------------
  403. // Entity
  404. // -------------------------------------------------------
  405. TDOMEntity = class(TDOMNode_WithChildren)
  406. protected
  407. FPublicID, FSystemID, FNotationName: DOMString;
  408. public
  409. constructor Create(AOwner: TDOMDocument);
  410. property PublicID: DOMString read FPublicID;
  411. property SystemID: DOMString read FSystemID;
  412. property NotationName: DOMString read FNotationName;
  413. end;
  414. // -------------------------------------------------------
  415. // EntityReference
  416. // -------------------------------------------------------
  417. TDOMEntityReference = class(TDOMNode_WithChildren)
  418. public
  419. constructor Create(AOwner: TDOMDocument);
  420. end;
  421. // -------------------------------------------------------
  422. // ProcessingInstruction
  423. // -------------------------------------------------------
  424. TDOMProcessingInstruction = class(TDOMNode)
  425. public
  426. constructor Create(AOwner: TDOMDocument);
  427. property Target: DOMString read FNodeName;
  428. property Data: DOMString read FNodeValue;
  429. end;
  430. // =======================================================
  431. // =======================================================
  432. implementation
  433. constructor TRefClass.Create;
  434. begin
  435. inherited Create;
  436. RefCounter := 1;
  437. end;
  438. function TRefClass.AddRef: LongInt;
  439. begin
  440. Inc(RefCounter);
  441. Result := RefCounter;
  442. end;
  443. function TRefClass.Release: LongInt;
  444. begin
  445. Dec(RefCounter);
  446. Result := RefCounter;
  447. if RefCounter <= 0 then Free;
  448. end;
  449. // -------------------------------------------------------
  450. // DOM Exception
  451. // -------------------------------------------------------
  452. constructor EDOMError.Create(ACode: Integer; const ASituation: String);
  453. begin
  454. Code := ACode;
  455. inherited Create(Self.ClassName + ' in ' + ASituation);
  456. end;
  457. constructor EDOMIndexSize.Create(const ASituation: String); // 1
  458. begin
  459. inherited Create(INDEX_SIZE_ERR, ASituation);
  460. end;
  461. constructor EDOMHierarchyRequest.Create(const ASituation: String); // 3
  462. begin
  463. inherited Create(HIERARCHY_REQUEST_ERR, ASituation);
  464. end;
  465. constructor EDOMWrongDocument.Create(const ASituation: String); // 4
  466. begin
  467. inherited Create(WRONG_DOCUMENT_ERR, ASituation);
  468. end;
  469. constructor EDOMNotFound.Create(const ASituation: String); // 8
  470. begin
  471. inherited Create(NOT_FOUND_ERR, ASituation);
  472. end;
  473. constructor EDOMNotSupported.Create(const ASituation: String); // 9
  474. begin
  475. inherited Create(NOT_SUPPORTED_ERR, ASituation);
  476. end;
  477. constructor EDOMInUseAttribute.Create(const ASituation: String); // 10
  478. begin
  479. inherited Create(INUSE_ATTRIBUTE_ERR, ASituation);
  480. end;
  481. constructor EDOMInvalidState.Create(const ASituation: String); // 11
  482. begin
  483. inherited Create(INVALID_STATE_ERR, ASituation);
  484. end;
  485. constructor EDOMSyntax.Create(const ASituation: String); // 12
  486. begin
  487. inherited Create(SYNTAX_ERR, ASituation);
  488. end;
  489. constructor EDOMInvalidModification.Create(const ASituation: String); // 13
  490. begin
  491. inherited Create(INVALID_MODIFICATION_ERR, ASituation);
  492. end;
  493. constructor EDOMNamespace.Create(const ASituation: String); // 14
  494. begin
  495. inherited Create(NAMESPACE_ERR, ASituation);
  496. end;
  497. constructor EDOMInvalidAccess.Create(const ASituation: String); // 15
  498. begin
  499. inherited Create(INVALID_ACCESS_ERR, ASituation);
  500. end;
  501. // -------------------------------------------------------
  502. // Node
  503. // -------------------------------------------------------
  504. constructor TDOMNode.Create(AOwner: TDOMDocument);
  505. begin
  506. FOwnerDocument := AOwner;
  507. inherited Create;
  508. end;
  509. function TDOMNode.GetNodeValue: DOMString;
  510. begin
  511. Result := FNodeValue;
  512. end;
  513. procedure TDOMNode.SetNodeValue(const AValue: DOMString);
  514. begin
  515. FNodeValue := AValue;
  516. end;
  517. function TDOMNode.GetChildNodes: TDOMNodeList;
  518. begin
  519. Result := TDOMNodeList.Create(Self, '*');
  520. end;
  521. function TDOMNode.GetFirstChild: TDOMNode;
  522. begin
  523. Result := nil;
  524. end;
  525. function TDOMNode.GetLastChild: TDOMNode;
  526. begin
  527. Result := nil;
  528. end;
  529. function TDOMNode.GetAttributes: TDOMNamedNodeMap;
  530. begin
  531. Result := nil;
  532. end;
  533. function TDOMNode.InsertBefore(NewChild, RefChild: TDOMNode): TDOMNode;
  534. begin
  535. raise EDOMHierarchyRequest.Create('Node.InsertBefore');
  536. if (NewChild=nil) and (RefChild=nil) then ;
  537. Result:=nil;
  538. end;
  539. function TDOMNode.ReplaceChild(NewChild, OldChild: TDOMNode): TDOMNode;
  540. begin
  541. raise EDOMHierarchyRequest.Create('Node.ReplaceChild');
  542. if (NewChild=nil) and (OldChild=nil) then ;
  543. Result:=nil;
  544. end;
  545. function TDOMNode.RemoveChild(OldChild: TDOMNode): TDOMNode;
  546. begin
  547. raise EDOMHierarchyRequest.Create('Node.RemoveChild');
  548. if (OldChild=nil) then ;
  549. Result:=nil;
  550. end;
  551. function TDOMNode.AppendChild(NewChild: TDOMNode): TDOMNode;
  552. begin
  553. raise EDOMHierarchyRequest.Create('Node.AppendChild');
  554. if (NewChild=nil) then ;
  555. Result:=nil;
  556. end;
  557. function TDOMNode.HasChildNodes: Boolean;
  558. begin
  559. Result := False;
  560. end;
  561. function TDOMNode.CloneNode(deep: Boolean): TDOMNode;
  562. begin
  563. Result:=CloneNode(deep, FOwnerDocument);
  564. if deep then ;
  565. end;
  566. function TDOMNode.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
  567. begin
  568. raise EDOMNotSupported.Create('CloneNode not implemented for ' + ClassName);
  569. if (deep) and (ACloneOwner=nil) then ;
  570. Result:=nil;
  571. end;
  572. function TDOMNode.FindNode(const ANodeName: DOMString): TDOMNode;
  573. var
  574. child: TDOMNode;
  575. begin
  576. child := FirstChild;
  577. while Assigned(child) do
  578. begin
  579. if child.NodeName = ANodeName then
  580. begin
  581. Result := child;
  582. exit;
  583. end;
  584. child := child.NextSibling;
  585. end;
  586. Result := nil;
  587. end;
  588. //------------------------------------------------------------------------------
  589. function CompareDOMStrings(const s1, s2: DOMPChar; l1, l2: integer): integer;
  590. var i: integer;
  591. begin
  592. Result:=l1-l2;
  593. i:=0;
  594. while (i<l1) and (Result=0) do begin
  595. Result:=ord(s1[i])-ord(s2[i]);
  596. inc(i);
  597. end;
  598. end;
  599. function CompareDOMNodeWithDOMNode(Node1, Node2: Pointer): integer;
  600. begin
  601. Result:=CompareDOMStrings(DOMPChar(TDOMNode(Node1).NodeName),
  602. DOMPChar(TDOMNode(Node2).NodeName),
  603. length(TDOMNode(Node1).NodeName),
  604. length(TDOMNode(Node2).NodeName)
  605. );
  606. end;
  607. function CompareDOMStringWithDOMNode(AKey, ANode: Pointer): integer;
  608. begin
  609. Result:=CompareDOMStrings(DOMPChar(AKey),
  610. DOMPChar(TDOMNode(ANode).NodeName),
  611. length(DOMString(AKey)),
  612. length(TDOMNode(ANode).NodeName)
  613. );
  614. end;
  615. function TDOMNode_WithChildren.GetFirstChild: TDOMNode;
  616. begin
  617. Result := FFirstChild;
  618. end;
  619. function TDOMNode_WithChildren.GetLastChild: TDOMNode;
  620. begin
  621. Result := FLastChild;
  622. end;
  623. destructor TDOMNode_WithChildren.Destroy;
  624. var
  625. child, next: TDOMNode;
  626. begin
  627. if FChildNodeTree<>nil then begin
  628. FChildNodeTree.Free;
  629. FChildNodeTree:=nil;
  630. end;
  631. child := FirstChild;
  632. while Assigned(child) do
  633. begin
  634. next := child.NextSibling;
  635. child.Free;
  636. child := next;
  637. end;
  638. inherited Destroy;
  639. end;
  640. function TDOMNode_WithChildren.InsertBefore(NewChild, RefChild: TDOMNode):
  641. TDOMNode;
  642. begin
  643. Result := NewChild;
  644. if not Assigned(RefChild) then
  645. begin
  646. AppendChild(NewChild);
  647. exit;
  648. end;
  649. if NewChild.FOwnerDocument <> FOwnerDocument then
  650. raise EDOMWrongDocument.Create('NodeWC.InsertBefore');
  651. if RefChild.ParentNode <> Self then
  652. raise EDOMHierarchyRequest.Create('NodeWC.InsertBefore');
  653. if NewChild.NodeType = DOCUMENT_FRAGMENT_NODE then
  654. raise EDOMNotSupported.Create('NodeWC.InsertBefore for DocumentFragment');
  655. NewChild.FNextSibling := RefChild;
  656. if RefChild = FFirstChild then
  657. FFirstChild := NewChild
  658. else
  659. begin
  660. RefChild.FPreviousSibling.FNextSibling := NewChild;
  661. NewChild.FPreviousSibling := RefChild.FPreviousSibling;
  662. end;
  663. RefChild.FPreviousSibling := NewChild;
  664. NewChild.FParentNode := Self;
  665. AddToChildNodeTree(NewChild);
  666. end;
  667. function TDOMNode_WithChildren.ReplaceChild(NewChild, OldChild: TDOMNode):
  668. TDOMNode;
  669. begin
  670. RemoveFromChildNodeTree(OldChild);
  671. InsertBefore(NewChild, OldChild);
  672. if Assigned(OldChild) then
  673. RemoveChild(OldChild);
  674. Result := NewChild;
  675. end;
  676. function TDOMNode_WithChildren.RemoveChild(OldChild: TDOMNode):
  677. TDOMNode;
  678. begin
  679. if OldChild.ParentNode <> Self then
  680. raise EDOMHierarchyRequest.Create('NodeWC.RemoveChild');
  681. if OldChild = FFirstChild then
  682. FFirstChild := FFirstChild.NextSibling
  683. else
  684. OldChild.FPreviousSibling.FNextSibling := OldChild.FNextSibling;
  685. if OldChild = FLastChild then
  686. FLastChild := FLastChild.FPreviousSibling
  687. else
  688. OldChild.FNextSibling.FPreviousSibling := OldChild.FPreviousSibling;
  689. RemoveFromChildNodeTree(OldChild);
  690. OldChild.Free;
  691. Result:=nil;
  692. end;
  693. function TDOMNode_WithChildren.AppendChild(NewChild: TDOMNode): TDOMNode;
  694. var
  695. Parent: TDOMNode;
  696. begin
  697. if NewChild.FOwnerDocument <> FOwnerDocument then
  698. raise EDOMWrongDocument.Create('NodeWC.AppendChild');
  699. Parent := Self;
  700. while Assigned(Parent) do
  701. begin
  702. if Parent = NewChild then
  703. raise EDOMHierarchyRequest.Create('NodeWC.AppendChild (cycle in tree)');
  704. Parent := Parent.ParentNode;
  705. end;
  706. if NewChild.FParentNode = Self then
  707. RemoveChild(NewChild);
  708. if NewChild.NodeType = DOCUMENT_FRAGMENT_NODE then
  709. raise EDOMNotSupported.Create('NodeWC.AppendChild for DocumentFragments')
  710. else begin
  711. if Assigned(FFirstChild) then
  712. begin
  713. FLastChild.FNextSibling := NewChild;
  714. NewChild.FPreviousSibling := FLastChild;
  715. end else
  716. FFirstChild := NewChild;
  717. FLastChild := NewChild;
  718. NewChild.FParentNode := Self;
  719. end;
  720. AddToChildNodeTree(NewChild);
  721. Result := NewChild;
  722. end;
  723. function TDOMNode_WithChildren.HasChildNodes: Boolean;
  724. begin
  725. Result := Assigned(FFirstChild);
  726. end;
  727. function TDOMNode_WithChildren.FindNode(const ANodeName: DOMString): TDOMNode;
  728. var AVLNode: TAVLTreeNode;
  729. begin
  730. Result:=nil;
  731. if FChildNodeTree<>nil then begin
  732. AVLNode:=FChildNodeTree.FindKey(DOMPChar(ANodeName),
  733. @CompareDOMStringWithDOMNode);
  734. if AVLNode<>nil then
  735. Result:=TDOMNode(AVLNode.Data);
  736. end;
  737. end;
  738. procedure TDOMNode_WithChildren.CloneChildren(ACopy: TDOMNode;
  739. ACloneOwner: TDOMDocument);
  740. var
  741. node: TDOMNode;
  742. begin
  743. node := FirstChild;
  744. while Assigned(node) do
  745. begin
  746. ACopy.AppendChild(node.CloneNode(True, ACloneOwner));
  747. node := node.NextSibling;
  748. end;
  749. end;
  750. procedure TDOMNode_WithChildren.AddToChildNodeTree(NewNode: TDOMNode);
  751. begin
  752. if FChildNodeTree=nil then
  753. FChildNodeTree:=TAVLTree.Create(@CompareDOMNodeWithDOMNode);
  754. if FChildNodeTree.Find(NewNode)=nil then
  755. FChildNodeTree.Add(NewNode);
  756. end;
  757. procedure TDOMNode_WithChildren.RemoveFromChildNodeTree(OldNode: TDOMNode);
  758. begin
  759. if FChildNodeTree<>nil then
  760. FChildNodeTree.Remove(OldNode);
  761. end;
  762. // -------------------------------------------------------
  763. // NodeList
  764. // -------------------------------------------------------
  765. constructor TDOMNodeList.Create(ANode: TDOMNode; const AFilter: DOMString);
  766. begin
  767. inherited Create;
  768. node := ANode;
  769. filter := AFilter;
  770. UseFilter := filter <> '*';
  771. end;
  772. function TDOMNodeList.GetCount: LongWord;
  773. var
  774. child: TDOMNode;
  775. begin
  776. if not UseFilter then
  777. begin
  778. Result := Count;
  779. exit;
  780. end;
  781. Result := 0;
  782. child := node.FirstChild;
  783. while Assigned(child) do
  784. begin
  785. if (not UseFilter) or (child.NodeName = filter) then
  786. Inc(Result);
  787. child := child.NextSibling;
  788. end;
  789. end;
  790. function TDOMNodeList.GetItem(index: LongWord): TDOMNode;
  791. var
  792. child: TDOMNode;
  793. begin
  794. Result := nil;
  795. child := node.FirstChild;
  796. If UseFilter Then
  797. begin
  798. while Assigned(child) do
  799. begin
  800. if (child.nodename=filter) then
  801. begin
  802. if index=0 then
  803. begin
  804. Result := child;
  805. break;
  806. end;
  807. dec(index);
  808. end;
  809. child := child.NextSibling;
  810. end;
  811. end
  812. else
  813. begin
  814. while Assigned(child) do
  815. begin
  816. if index = 0 then
  817. begin
  818. Result := child;
  819. break;
  820. end;
  821. Dec(index);
  822. child := child.NextSibling;
  823. end;
  824. end
  825. end;
  826. // -------------------------------------------------------
  827. // NamedNodeMap
  828. // -------------------------------------------------------
  829. constructor TDOMNamedNodeMap.Create(AOwner: TDOMDocument);
  830. begin
  831. inherited Create;
  832. OwnerDocument := AOwner;
  833. end;
  834. function TDOMNamedNodeMap.GetItem(index: LongWord): TDOMNode;
  835. begin
  836. Result := TDOMNode(Items[index]);
  837. end;
  838. procedure TDOMNamedNodeMap.SetItem(index: LongWord; AItem: TDOMNode);
  839. begin
  840. Items[index] := AItem;
  841. end;
  842. function TDOMNamedNodeMap.GetLength: LongWord;
  843. begin
  844. Result := Count;
  845. end;
  846. function TDOMNamedNodeMap.GetNamedItem(const name: DOMString): TDOMNode;
  847. var
  848. i: Integer;
  849. begin
  850. for i := 0 to Count - 1 do
  851. begin
  852. Result := Item[i];
  853. if Result.NodeName = name then
  854. exit;
  855. end;
  856. Result := nil;
  857. end;
  858. function TDOMNamedNodeMap.SetNamedItem(arg: TDOMNode): TDOMNode;
  859. var
  860. i: Integer;
  861. begin
  862. if arg.FOwnerDocument <> OwnerDocument then
  863. raise EDOMWrongDocument.Create('NamedNodeMap.SetNamedItem');
  864. if arg.NodeType = ATTRIBUTE_NODE then
  865. begin
  866. if Assigned(TDOMAttr(arg).AttrOwner) then
  867. raise EDOMInUseAttribute.Create('NamedNodeMap.SetNamedItem');
  868. TDOMAttr(arg).AttrOwner := Self;
  869. end;
  870. for i := 0 to Count - 1 do
  871. if Item[i].NodeName = arg.NodeName then
  872. begin
  873. Result := Item[i];
  874. Item[i] := arg;
  875. exit;
  876. end;
  877. Add(arg);
  878. Result := nil;
  879. end;
  880. function TDOMNamedNodeMap.RemoveNamedItem(const name: DOMString): TDOMNode;
  881. var
  882. i: Integer;
  883. begin
  884. for i := 0 to Count - 1 do
  885. if Item[i].NodeName = name then
  886. begin
  887. Result := Item[i];
  888. Result.FParentNode := nil;
  889. exit;
  890. end;
  891. raise EDOMNotFound.Create('NamedNodeMap.RemoveNamedItem');
  892. end;
  893. // -------------------------------------------------------
  894. // CharacterData
  895. // -------------------------------------------------------
  896. function TDOMCharacterData.GetLength: LongWord;
  897. begin
  898. Result := system.Length(FNodeValue);
  899. end;
  900. function TDOMCharacterData.SubstringData(offset, count: LongWord): DOMString;
  901. begin
  902. if (offset > Length) then
  903. raise EDOMIndexSize.Create('CharacterData.SubstringData');
  904. Result := Copy(FNodeValue, offset + 1, count);
  905. end;
  906. procedure TDOMCharacterData.AppendData(const arg: DOMString);
  907. begin
  908. FNodeValue := FNodeValue + arg;
  909. end;
  910. procedure TDOMCharacterData.InsertData(offset: LongWord; const arg: DOMString);
  911. begin
  912. if (offset > Length) then
  913. raise EDOMIndexSize.Create('CharacterData.InsertData');
  914. FNodeValue := Copy(FNodeValue, 1, offset) + arg +
  915. Copy(FNodeValue, offset + 1, Length);
  916. end;
  917. procedure TDOMCharacterData.DeleteData(offset, count: LongWord);
  918. begin
  919. if (offset > Length) then
  920. raise EDOMIndexSize.Create('CharacterData.DeleteData');
  921. FNodeValue := Copy(FNodeValue, 1, offset) +
  922. Copy(FNodeValue, offset + count + 1, Length);
  923. end;
  924. procedure TDOMCharacterData.ReplaceData(offset, count: LongWord; const arg: DOMString);
  925. begin
  926. DeleteData(offset, count);
  927. InsertData(offset, arg);
  928. end;
  929. // -------------------------------------------------------
  930. // DocumentFragmet
  931. // -------------------------------------------------------
  932. constructor TDOMDocumentFragment.Create(AOwner: TDOMDocument);
  933. begin
  934. FNodeType := DOCUMENT_FRAGMENT_NODE;
  935. FNodeName := '#document-fragment';
  936. inherited Create(AOwner);
  937. end;
  938. // -------------------------------------------------------
  939. // DOMImplementation
  940. // -------------------------------------------------------
  941. function TDOMImplementation.HasFeature(const feature, version: DOMString):
  942. Boolean;
  943. begin
  944. Result := False;
  945. if (feature='') and (version='') then ;
  946. end;
  947. function TDOMImplementation.CreateDocumentType(const QualifiedName, PublicID,
  948. SystemID: DOMString): TDOMDocumentType;
  949. begin
  950. // !!!: Implement this method (easy to do)
  951. raise EDOMNotSupported.Create('DOMImplementation.CreateDocumentType');
  952. if (QualifiedName='') and (PublicID='') and (SystemID='') then ;
  953. Result:=nil;
  954. end;
  955. function TDOMImplementation.CreateDocument(const NamespaceURI,
  956. QualifiedName: DOMString; doctype: TDOMDocumentType): TDOMDocument;
  957. begin
  958. // !!!: Implement this method (easy to do)
  959. raise EDOMNotSupported.Create('DOMImplementation.CreateDocument');
  960. if (NamespaceURI='') and (QualifiedName='') and (doctype=nil) then ;
  961. Result:=nil;
  962. end;
  963. // -------------------------------------------------------
  964. // Document
  965. // -------------------------------------------------------
  966. constructor TDOMDocument.Create;
  967. begin
  968. FNodeType := DOCUMENT_NODE;
  969. FNodeName := '#document';
  970. inherited Create(nil);
  971. FOwnerDocument := Self;
  972. end;
  973. function TDOMDocument.GetDocumentElement: TDOMElement;
  974. var
  975. node: TDOMNode;
  976. begin
  977. node := FFirstChild;
  978. while Assigned(node) do
  979. begin
  980. if node.FNodeType = ELEMENT_NODE then
  981. begin
  982. Result := TDOMElement(node);
  983. exit;
  984. end;
  985. node := node.NextSibling;
  986. end;
  987. Result := nil;
  988. end;
  989. function TDOMDocument.CreateElement(const tagName: DOMString): TDOMElement;
  990. begin
  991. Result := TDOMElement.Create(Self);
  992. Result.FNodeName := tagName;
  993. end;
  994. function TDOMDocument.CreateDocumentFragment: TDOMDocumentFragment;
  995. begin
  996. Result := TDOMDocumentFragment.Create(Self);
  997. end;
  998. function TDOMDocument.CreateTextNode(const data: DOMString): TDOMText;
  999. begin
  1000. Result := TDOMText.Create(Self);
  1001. Result.FNodeValue := data;
  1002. end;
  1003. function TDOMDocument.CreateComment(const data: DOMString): TDOMComment;
  1004. begin
  1005. Result := TDOMComment.Create(Self);
  1006. Result.FNodeValue := data;
  1007. end;
  1008. function TDOMDocument.CreateCDATASection(const data: DOMString):
  1009. TDOMCDATASection;
  1010. begin
  1011. raise EDOMNotSupported.Create('DOMDocument.CreateCDATASection');
  1012. if data='' then ;
  1013. Result:=nil;
  1014. end;
  1015. function TDOMDocument.CreateProcessingInstruction(const target,
  1016. data: DOMString): TDOMProcessingInstruction;
  1017. begin
  1018. raise EDOMNotSupported.Create('DOMDocument.CreateProcessingInstruction');
  1019. if (target='') and (data='') then ;
  1020. Result:=nil;
  1021. end;
  1022. function TDOMDocument.CreateAttribute(const name: DOMString): TDOMAttr;
  1023. begin
  1024. Result := TDOMAttr.Create(Self);
  1025. Result.FNodeName := name;
  1026. end;
  1027. function TDOMDocument.CreateEntityReference(const name: DOMString):
  1028. TDOMEntityReference;
  1029. begin
  1030. raise EDOMNotSupported.Create('DOMDocument.CreateEntityReference');
  1031. if name='' then ;
  1032. Result:=nil;
  1033. end;
  1034. function TDOMDocument.CreateEntity(const data: DOMString): TDOMEntity;
  1035. begin
  1036. Result := TDOMEntity.Create(Self);
  1037. Result.FNodeName := data;
  1038. end;
  1039. function TDOMDocument.GetElementsByTagName(const tagname: DOMString): TDOMNodeList;
  1040. begin
  1041. Result := TDOMNodeList.Create(Self, tagname);
  1042. end;
  1043. function TXMLDocument.CreateCDATASection(const data: DOMString):
  1044. TDOMCDATASection;
  1045. begin
  1046. Result := TDOMCDATASection.Create(Self);
  1047. Result.FNodeValue := data;
  1048. end;
  1049. function TXMLDocument.CreateProcessingInstruction(const target,
  1050. data: DOMString): TDOMProcessingInstruction;
  1051. begin
  1052. Result := TDOMProcessingInstruction.Create(Self);
  1053. Result.FNodeName := target;
  1054. Result.FNodeValue := data;
  1055. end;
  1056. function TXMLDocument.CreateEntityReference(const name: DOMString):
  1057. TDOMEntityReference;
  1058. begin
  1059. Result := TDOMEntityReference.Create(Self);
  1060. Result.FNodeName := name;
  1061. end;
  1062. // -------------------------------------------------------
  1063. // Attr
  1064. // -------------------------------------------------------
  1065. constructor TDOMAttr.Create(AOwner: TDOMDocument);
  1066. begin
  1067. FNodeType := ATTRIBUTE_NODE;
  1068. inherited Create(AOwner);
  1069. end;
  1070. function TDOMAttr.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
  1071. begin
  1072. Result := TDOMAttr.Create(ACloneOwner);
  1073. Result.FNodeName := FNodeName;
  1074. TDOMAttr(Result).FSpecified := FSpecified;
  1075. if deep then
  1076. CloneChildren(Result, ACloneOwner);
  1077. end;
  1078. function TDOMAttr.GetNodeValue: DOMString;
  1079. var
  1080. child: TDOMNode;
  1081. begin
  1082. SetLength(Result, 0);
  1083. if Assigned(FFirstChild) then
  1084. begin
  1085. child := FFirstChild;
  1086. while Assigned(child) do
  1087. begin
  1088. if child.NodeType = ENTITY_REFERENCE_NODE then
  1089. Result := Result + '&' + child.NodeName + ';'
  1090. else
  1091. Result := Result + child.NodeValue;
  1092. child := child.NextSibling;
  1093. end;
  1094. end;
  1095. end;
  1096. procedure TDOMAttr.SetNodeValue(const AValue: DOMString);
  1097. var
  1098. tn: TDOMText;
  1099. begin
  1100. FSpecified := True;
  1101. tn := TDOMText.Create(FOwnerDocument);
  1102. tn.FNodeValue := AValue;
  1103. if Assigned(FFirstChild) then
  1104. ReplaceChild(tn, FFirstChild)
  1105. else
  1106. AppendChild(tn);
  1107. end;
  1108. // -------------------------------------------------------
  1109. // Element
  1110. // -------------------------------------------------------
  1111. constructor TDOMElement.Create(AOwner: TDOMDocument);
  1112. begin
  1113. FNodeType := ELEMENT_NODE;
  1114. inherited Create(AOwner);
  1115. end;
  1116. destructor TDOMElement.Destroy;
  1117. var
  1118. i: Integer;
  1119. begin
  1120. {As the attributes are _not_ childs of the element node, we have to free
  1121. them manually here:}
  1122. if FAttributes<>nil then begin
  1123. for i := 0 to FAttributes.Count - 1 do
  1124. FAttributes[i].Free;
  1125. FAttributes.Free;
  1126. FAttributes:=nil;
  1127. end;
  1128. inherited Destroy;
  1129. end;
  1130. function TDOMElement.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
  1131. var
  1132. i: Integer;
  1133. begin
  1134. Result := TDOMElement.Create(ACloneOwner);
  1135. Result.FNodeName := FNodeName;
  1136. if FAttributes<>nil then begin
  1137. TDOMElement(Result).GetAttributes;
  1138. for i := 0 to FAttributes.Count - 1 do
  1139. TDOMElement(Result).FAttributes.Add(FAttributes[i].CloneNode(True, ACloneOwner));
  1140. end;
  1141. if deep then
  1142. CloneChildren(Result, ACloneOwner);
  1143. end;
  1144. function TDOMElement.GetAttributes: TDOMNamedNodeMap;
  1145. begin
  1146. if FAttributes=nil then
  1147. FAttributes := TDOMNamedNodeMap.Create(FOwnerDocument);
  1148. Result := FAttributes;
  1149. end;
  1150. function TDOMElement.GetAttribute(const name: DOMString): DOMString;
  1151. var
  1152. i: Integer;
  1153. begin
  1154. if FAttributes<>nil then begin
  1155. for i := 0 to FAttributes.Count - 1 do
  1156. if FAttributes[i].NodeName = name then
  1157. begin
  1158. Result := FAttributes[i].NodeValue;
  1159. exit;
  1160. end;
  1161. end;
  1162. SetLength(Result, 0);
  1163. end;
  1164. procedure TDOMElement.SetAttribute(const name, value: DOMString);
  1165. var
  1166. i: Integer;
  1167. attr: TDOMAttr;
  1168. begin
  1169. GetAttributes;
  1170. for i := 0 to FAttributes.Count - 1 do
  1171. if FAttributes[i].NodeName = name then
  1172. begin
  1173. FAttributes[i].NodeValue := value;
  1174. exit;
  1175. end;
  1176. attr := TDOMAttr.Create(FOwnerDocument);
  1177. attr.FNodeName := name;
  1178. attr.NodeValue := value;
  1179. FAttributes.Add(attr);
  1180. end;
  1181. procedure TDOMElement.RemoveAttribute(const name: DOMString);
  1182. var
  1183. i: Integer;
  1184. begin
  1185. if FAttributes=nil then exit;
  1186. for i := 0 to FAttributes.Count - 1 do
  1187. if FAttributes[i].NodeName = name then
  1188. begin
  1189. FAttributes[i].Free;
  1190. FAttributes.Delete(i);
  1191. exit;
  1192. end;
  1193. end;
  1194. function TDOMElement.GetAttributeNode(const name: DOMString): TDOMAttr;
  1195. var
  1196. i: Integer;
  1197. begin
  1198. if FAttributes<>nil then begin
  1199. for i := 0 to FAttributes.Count - 1 do
  1200. if FAttributes[i].NodeName = name then
  1201. begin
  1202. Result := TDOMAttr(FAttributes[i]);
  1203. exit;
  1204. end;
  1205. end;
  1206. Result := nil;
  1207. end;
  1208. procedure TDOMElement.SetAttributeNode(NewAttr: TDOMAttr);
  1209. var
  1210. i: Integer;
  1211. begin
  1212. if FAttributes=nil then exit;
  1213. for i := 0 to FAttributes.Count - 1 do
  1214. if FAttributes[i].NodeName = NewAttr.NodeName then
  1215. begin
  1216. FAttributes[i].Free;
  1217. FAttributes[i] := NewAttr;
  1218. exit;
  1219. end;
  1220. end;
  1221. function TDOMElement.RemoveAttributeNode(OldAttr: TDOMAttr): TDOMAttr;
  1222. var
  1223. i: Integer;
  1224. node: TDOMNode;
  1225. begin
  1226. Result:=nil;
  1227. if FAttributes=nil then exit;
  1228. for i := 0 to FAttributes.Count - 1 do
  1229. begin
  1230. node := FAttributes[i];
  1231. if node = OldAttr then
  1232. begin
  1233. FAttributes.Delete(i);
  1234. Result := TDOMAttr(node);
  1235. exit;
  1236. end;
  1237. end;
  1238. end;
  1239. function TDOMElement.GetElementsByTagName(const name: DOMString): TDOMNodeList;
  1240. begin
  1241. Result := TDOMNodeList.Create(Self, name);
  1242. end;
  1243. procedure TDOMElement.Normalize;
  1244. begin
  1245. // !!!: Not implemented
  1246. end;
  1247. // -------------------------------------------------------
  1248. // Text
  1249. // -------------------------------------------------------
  1250. constructor TDOMText.Create(AOwner: TDOMDocument);
  1251. begin
  1252. FNodeType := TEXT_NODE;
  1253. FNodeName := '#text';
  1254. inherited Create(AOwner);
  1255. end;
  1256. function TDOMText.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
  1257. begin
  1258. Result := TDOMText.Create(ACloneOwner);
  1259. Result.FNodeValue := FNodeValue;
  1260. if deep and (ACloneOwner=nil) then ;
  1261. end;
  1262. function TDOMText.SplitText(offset: LongWord): TDOMText;
  1263. begin
  1264. if offset > Length then
  1265. raise EDOMIndexSize.Create('Text.SplitText');
  1266. Result := TDOMText.Create(FOwnerDocument);
  1267. Result.FNodeValue := Copy(FNodeValue, offset + 1, Length);
  1268. FNodeValue := Copy(FNodeValue, 1, offset);
  1269. FParentNode.InsertBefore(Result, FNextSibling);
  1270. end;
  1271. // -------------------------------------------------------
  1272. // Comment
  1273. // -------------------------------------------------------
  1274. constructor TDOMComment.Create(AOwner: TDOMDocument);
  1275. begin
  1276. FNodeType := COMMENT_NODE;
  1277. FNodeName := '#comment';
  1278. inherited Create(AOwner);
  1279. end;
  1280. function TDOMComment.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
  1281. begin
  1282. Result := TDOMComment.Create(ACloneOwner);
  1283. Result.FNodeValue := FNodeValue;
  1284. if deep and (ACloneOwner=nil) then ;
  1285. end;
  1286. // -------------------------------------------------------
  1287. // CDATASection
  1288. // -------------------------------------------------------
  1289. constructor TDOMCDATASection.Create(AOwner: TDOMDocument);
  1290. begin
  1291. inherited Create(AOwner);
  1292. FNodeType := CDATA_SECTION_NODE;
  1293. FNodeName := '#cdata-section';
  1294. end;
  1295. function TDOMCDATASection.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
  1296. begin
  1297. Result := TDOMCDATASection.Create(ACloneOwner);
  1298. Result.FNodeValue := FNodeValue;
  1299. if deep and (ACloneOwner=nil) then ;
  1300. end;
  1301. // -------------------------------------------------------
  1302. // DocumentType
  1303. // -------------------------------------------------------
  1304. constructor TDOMDocumentType.Create(AOwner: TDOMDocument);
  1305. begin
  1306. FNodeType := DOCUMENT_TYPE_NODE;
  1307. inherited Create(AOwner);
  1308. end;
  1309. function TDOMDocumentType.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
  1310. begin
  1311. Result := TDOMDocumentType.Create(ACloneOwner);
  1312. Result.FNodeName := FNodeName;
  1313. if deep and (ACloneOwner=nil) then ;
  1314. end;
  1315. // -------------------------------------------------------
  1316. // Notation
  1317. // -------------------------------------------------------
  1318. constructor TDOMNotation.Create(AOwner: TDOMDocument);
  1319. begin
  1320. FNodeType := NOTATION_NODE;
  1321. inherited Create(AOwner);
  1322. end;
  1323. function TDOMNotation.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
  1324. begin
  1325. Result := TDOMNotation.Create(ACloneOwner);
  1326. Result.FNodeName := FNodeName;
  1327. if deep and (ACloneOwner=nil) then ;
  1328. end;
  1329. // -------------------------------------------------------
  1330. // Entity
  1331. // -------------------------------------------------------
  1332. constructor TDOMEntity.Create(AOwner: TDOMDocument);
  1333. begin
  1334. FNodeType := ENTITY_NODE;
  1335. inherited Create(AOwner);
  1336. end;
  1337. // -------------------------------------------------------
  1338. // EntityReference
  1339. // -------------------------------------------------------
  1340. constructor TDOMEntityReference.Create(AOwner: TDOMDocument);
  1341. begin
  1342. FNodeType := ENTITY_REFERENCE_NODE;
  1343. inherited Create(AOwner);
  1344. end;
  1345. // -------------------------------------------------------
  1346. // ProcessingInstruction
  1347. // -------------------------------------------------------
  1348. constructor TDOMProcessingInstruction.Create(AOwner: TDOMDocument);
  1349. begin
  1350. FNodeType := PROCESSING_INSTRUCTION_NODE;
  1351. inherited Create(AOwner);
  1352. end;
  1353. end.