dom.pp 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337
  1. {
  2. $Id$
  3. This file is part of the Free Component Library
  4. Copyright (c) 1999-2000 by Sebastian Guenther
  5. Implementation of DOM level 1 interfaces
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {
  13. more or less DOM level 1 conformant class library for Free Pascal
  14. }
  15. {$MODE objfpc}
  16. {$H+}
  17. unit DOM;
  18. interface
  19. uses sysutils, classes;
  20. type
  21. TDOMImplementation = class;
  22. TDOMDocumentFragment = class;
  23. TDOMDocument = class;
  24. TDOMNode = class;
  25. TDOMNodeList = class;
  26. TDOMNamedNodeMap = class;
  27. TDOMCharacterData = class;
  28. TDOMAttr = class;
  29. TDOMElement = class;
  30. TDOMText = class;
  31. TDOMComment = class;
  32. TDOMCDATASection = class;
  33. TDOMDocumentType = class;
  34. TDOMNotation = class;
  35. TDOMEntity = class;
  36. TDOMEntityReference = class;
  37. TDOMProcessingInstruction = class;
  38. // -------------------------------------------------------
  39. // DOMString
  40. // -------------------------------------------------------
  41. DOMString = String; // *** should be WideString /sg
  42. // -------------------------------------------------------
  43. // DOMException
  44. // -------------------------------------------------------
  45. const
  46. INDEX_SIZE_ERR = 1;
  47. DOMSTRING_SIZE_ERR = 2;
  48. HIERARCHY_REQUEST_ERR = 3;
  49. WRONG_DOCUMENT_ERR = 4;
  50. INVALID_CHARACTER_ERR = 5;
  51. NO_DATA_ALLOWED_ERR = 6;
  52. NO_MODIFICATION_ALLOWED_ERR = 7;
  53. NOT_FOUND_ERR = 8;
  54. NOT_SUPPORTED_ERR = 9;
  55. INUSE_ATTRIBUTE_ERR = 10;
  56. type
  57. EDOMError = class(Exception)
  58. protected
  59. constructor Create(ACode: Integer; const ASituation: String);
  60. public
  61. Code: Integer;
  62. end;
  63. EDOMIndexSize = class(EDOMError)
  64. public
  65. constructor Create(const ASituation: String);
  66. end;
  67. EDOMHierarchyRequest = class(EDOMError)
  68. public
  69. constructor Create(const ASituation: String);
  70. end;
  71. EDOMWrongDocument = class(EDOMError)
  72. public
  73. constructor Create(const ASituation: String);
  74. end;
  75. EDOMNotFound = class(EDOMError)
  76. public
  77. constructor Create(const ASituation: String);
  78. end;
  79. EDOMNotSupported = class(EDOMError)
  80. public
  81. constructor Create(const ASituation: String);
  82. end;
  83. EDOMInUseAttribute = class(EDOMError)
  84. public
  85. constructor Create(const ASituation: String);
  86. end;
  87. // -------------------------------------------------------
  88. // Node
  89. // -------------------------------------------------------
  90. const
  91. ELEMENT_NODE = 1;
  92. ATTRIBUTE_NODE = 2;
  93. TEXT_NODE = 3;
  94. CDATA_SECTION_NODE = 4;
  95. ENTITY_REFERENCE_NODE = 5;
  96. ENTITY_NODE = 6;
  97. PROCESSING_INSTRUCTION_NODE = 7;
  98. COMMENT_NODE = 8;
  99. DOCUMENT_NODE = 9;
  100. DOCUMENT_TYPE_NODE = 10;
  101. DOCUMENT_FRAGMENT_NODE = 11;
  102. NOTATION_NODE = 12;
  103. type
  104. TRefClass = class
  105. protected
  106. RefCounter: LongInt;
  107. public
  108. constructor Create;
  109. function AddRef: LongInt; virtual;
  110. function Release: LongInt; virtual;
  111. end;
  112. TDOMNode = class
  113. protected
  114. FNodeName, FNodeValue: DOMString;
  115. FNodeType: Integer;
  116. FParentNode: TDOMNode;
  117. FPreviousSibling, FNextSibling: TDOMNode;
  118. FOwnerDocument: TDOMDocument;
  119. function GetNodeValue: DOMString; virtual;
  120. procedure SetNodeValue(AValue: DOMString); virtual;
  121. function GetFirstChild: TDOMNode; virtual;
  122. function GetLastChild: TDOMNode; virtual;
  123. function GetAttributes: TDOMNamedNodeMap; virtual;
  124. constructor Create(AOwner: TDOMDocument);
  125. public
  126. // Free NodeList with TDOMNodeList.Release!
  127. function GetChildNodes: TDOMNodeList; virtual;
  128. property NodeName: DOMString read FNodeName;
  129. property NodeValue: DOMString read GetNodeValue write SetNodeValue;
  130. property NodeType: Integer read FNodeType;
  131. property ParentNode: TDOMNode read FParentNode;
  132. property FirstChild: TDOMNode read GetFirstChild;
  133. property LastChild: TDOMNode read GetLastChild;
  134. property ChildNodes: TDOMNodeList read GetChildNodes;
  135. property PreviousSibling: TDOMNode read FPreviousSibling;
  136. property NextSibling: TDOMNode read FNextSibling;
  137. property Attributes: TDOMNamedNodeMap read GetAttributes;
  138. property OwnerDocument: TDOMDocument read FOwnerDocument;
  139. function InsertBefore(NewChild, RefChild: TDOMNode): TDOMNode; virtual;
  140. function ReplaceChild(NewChild, OldChild: TDOMNode): TDOMNode; virtual;
  141. function RemoveChild(OldChild: TDOMNode): TDOMNode; virtual;
  142. function AppendChild(NewChild: TDOMNode): TDOMNode; virtual;
  143. function HasChildNodes: Boolean; virtual;
  144. function CloneNode(deep: Boolean): TDOMNode;
  145. // Extensions to DOM interface:
  146. function FindNode(const ANodeName: DOMString): TDOMNode;
  147. end;
  148. { The following class is an implementation specific extension, it is just an
  149. extended implementation of TDOMNode, the generic DOM::Node interface
  150. implementation. (Its main purpose is to save memory in a big node tree) }
  151. TDOMNode_WithChildren = class(TDOMNode)
  152. protected
  153. FFirstChild, FLastChild: TDOMNode;
  154. function GetFirstChild: TDOMNode; override;
  155. function GetLastChild: TDOMNode; override;
  156. public
  157. destructor Destroy; override;
  158. function InsertBefore(NewChild, RefChild: TDOMNode): TDOMNode; override;
  159. function ReplaceChild(NewChild, OldChild: TDOMNode): TDOMNode; override;
  160. function RemoveChild(OldChild: TDOMNode): TDOMNode; override;
  161. function AppendChild(NewChild: TDOMNode): TDOMNode; override;
  162. function HasChildNodes: Boolean; override;
  163. end;
  164. // -------------------------------------------------------
  165. // NodeList
  166. // -------------------------------------------------------
  167. TDOMNodeList = class(TRefClass)
  168. protected
  169. node: TDOMNode;
  170. filter: DOMString;
  171. UseFilter: Boolean;
  172. constructor Create(ANode: TDOMNode; AFilter: DOMString);
  173. function GetCount: LongWord;
  174. function GetItem(index: LongWord): TDOMNode;
  175. public
  176. property Item[index: LongWord]: TDOMNode read GetItem;
  177. property Count: LongWord read GetCount;
  178. end;
  179. // -------------------------------------------------------
  180. // NamedNodeMap
  181. // -------------------------------------------------------
  182. TDOMNamedNodeMap = class(TList)
  183. protected
  184. OwnerDocument: TDOMDocument;
  185. function GetItem(index: LongWord): TDOMNode;
  186. procedure SetItem(index: LongWord; AItem: TDOMNode);
  187. function GetLength: LongWord;
  188. constructor Create(AOwner: TDOMDocument);
  189. public
  190. function GetNamedItem(const name: DOMString): TDOMNode;
  191. function SetNamedItem(arg: TDOMNode): TDOMNode;
  192. function RemoveNamedItem(const name: DOMString): TDOMNode;
  193. property Item[index: LongWord]: TDOMNode read GetItem write SetItem;
  194. property Length: LongWord read GetLength;
  195. end;
  196. // -------------------------------------------------------
  197. // CharacterData
  198. // -------------------------------------------------------
  199. TDOMCharacterData = class(TDOMNode)
  200. protected
  201. function GetLength: LongWord;
  202. public
  203. property Data: DOMString read FNodeValue;
  204. property Length: LongWord read GetLength;
  205. function SubstringData(offset, count: LongWord): DOMString;
  206. procedure AppendData(const arg: DOMString);
  207. procedure InsertData(offset: LongWord; const arg: DOMString);
  208. procedure DeleteData(offset, count: LongWord);
  209. procedure ReplaceData(offset, count: LongWord; const arg: DOMString);
  210. end;
  211. // -------------------------------------------------------
  212. // DOMImplementation
  213. // -------------------------------------------------------
  214. TDOMImplementation = class
  215. public
  216. function HasFeature(const feature, version: DOMString): Boolean;
  217. end;
  218. // -------------------------------------------------------
  219. // DocumentFragment
  220. // -------------------------------------------------------
  221. TDOMDocumentFragment = class(TDOMNode_WithChildren)
  222. protected
  223. constructor Create(AOwner: TDOMDocument);
  224. end;
  225. // -------------------------------------------------------
  226. // Document
  227. // -------------------------------------------------------
  228. TDOMDocument = class(TDOMNode_WithChildren)
  229. protected
  230. FDocType: TDOMDocumentType;
  231. FImplementation: TDOMImplementation;
  232. function GetDocumentElement: TDOMElement;
  233. public
  234. property DocType: TDOMDocumentType read FDocType;
  235. property Impl: TDOMImplementation read FImplementation;
  236. property DocumentElement: TDOMElement read GetDocumentElement;
  237. function CreateElement(const tagName: DOMString): TDOMElement; virtual;
  238. function CreateDocumentFragment: TDOMDocumentFragment;
  239. function CreateTextNode(const data: DOMString): TDOMText;
  240. function CreateComment(const data: DOMString): TDOMComment;
  241. function CreateCDATASection(const data: DOMString): TDOMCDATASection;
  242. virtual;
  243. function CreateProcessingInstruction(const target, data: DOMString):
  244. TDOMProcessingInstruction; virtual;
  245. function CreateAttribute(const name: DOMString): TDOMAttr; virtual;
  246. function CreateEntityReference(const name: DOMString): TDOMEntityReference;
  247. virtual;
  248. // Free NodeList with TDOMNodeList.Release!
  249. function GetElementsByTagName(const tagname: DOMString): TDOMNodeList;
  250. // Extensions to DOM interface:
  251. constructor Create; virtual;
  252. function CreateEntity(const data: DOMString): TDOMEntity;
  253. end;
  254. TXMLDocument = class(TDOMDocument)
  255. public
  256. function CreateCDATASection(const data: DOMString): TDOMCDATASection;
  257. virtual;
  258. function CreateProcessingInstruction(const target, data: DOMString):
  259. TDOMProcessingInstruction; virtual;
  260. function CreateEntityReference(const name: DOMString): TDOMEntityReference;
  261. virtual;
  262. // Extensions to DOM interface:
  263. XMLVersion, Encoding: String;
  264. end;
  265. // -------------------------------------------------------
  266. // Attr
  267. // -------------------------------------------------------
  268. TDOMAttr = class(TDOMNode_WithChildren)
  269. protected
  270. FSpecified: Boolean;
  271. AttrOwner: TDOMNamedNodeMap;
  272. function GetNodeValue: DOMString; override;
  273. procedure SetNodeValue(AValue: DOMString); override;
  274. constructor Create(AOwner: TDOMDocument);
  275. public
  276. property Name: DOMString read FNodeName;
  277. property Specified: Boolean read FSpecified;
  278. property Value: DOMString read FNodeValue write SetNodeValue;
  279. end;
  280. // -------------------------------------------------------
  281. // Element
  282. // -------------------------------------------------------
  283. TDOMElement = class(TDOMNode_WithChildren)
  284. protected
  285. FAttributes: TDOMNamedNodeMap;
  286. function GetAttributes: TDOMNamedNodeMap; override;
  287. constructor Create(AOwner: TDOMDocument); virtual;
  288. public
  289. destructor Destroy; override;
  290. property TagName: DOMString read FNodeName;
  291. function GetAttribute(const name: DOMString): DOMString;
  292. procedure SetAttribute(const name, value: DOMString);
  293. procedure RemoveAttribute(const name: DOMString);
  294. function GetAttributeNode(const name: DOMString): TDOMAttr;
  295. procedure SetAttributeNode(NewAttr: TDOMAttr);
  296. function RemoveAttributeNode(OldAttr: TDOMAttr): TDOMAttr;
  297. // Free NodeList with TDOMNodeList.Release!
  298. function GetElementsByTagName(const name: DOMString): TDOMNodeList;
  299. procedure Normalize;
  300. end;
  301. // -------------------------------------------------------
  302. // Text
  303. // -------------------------------------------------------
  304. TDOMText = class(TDOMCharacterData)
  305. protected
  306. constructor Create(AOwner: TDOMDocument);
  307. public
  308. function SplitText(offset: LongWord): TDOMText;
  309. end;
  310. // -------------------------------------------------------
  311. // Comment
  312. // -------------------------------------------------------
  313. TDOMComment = class(TDOMCharacterData)
  314. protected
  315. constructor Create(AOwner: TDOMDocument);
  316. end;
  317. // -------------------------------------------------------
  318. // CDATASection
  319. // -------------------------------------------------------
  320. TDOMCDATASection = class(TDOMText)
  321. protected
  322. constructor Create(AOwner: TDOMDocument);
  323. end;
  324. // -------------------------------------------------------
  325. // DocumentType
  326. // -------------------------------------------------------
  327. TDOMDocumentType = class(TDOMNode)
  328. protected
  329. FEntities, FNotations: TDOMNamedNodeMap;
  330. constructor Create(AOwner: TDOMDocument);
  331. public
  332. property Name: DOMString read FNodeName;
  333. property Entities: TDOMNamedNodeMap read FEntities;
  334. property Notations: TDOMNamedNodeMap read FEntities;
  335. end;
  336. // -------------------------------------------------------
  337. // Notation
  338. // -------------------------------------------------------
  339. TDOMNotation = class(TDOMNode)
  340. protected
  341. FPublicID, FSystemID: DOMString;
  342. constructor Create(AOwner: TDOMDocument);
  343. public
  344. property PublicID: DOMString read FPublicID;
  345. property SystemID: DOMString read FSystemID;
  346. end;
  347. // -------------------------------------------------------
  348. // Entity
  349. // -------------------------------------------------------
  350. TDOMEntity = class(TDOMNode_WithChildren)
  351. protected
  352. FPublicID, FSystemID, FNotationName: DOMString;
  353. constructor Create(AOwner: TDOMDocument);
  354. public
  355. property PublicID: DOMString read FPublicID;
  356. property SystemID: DOMString read FSystemID;
  357. property NotationName: DOMString read FNotationName;
  358. end;
  359. // -------------------------------------------------------
  360. // EntityReference
  361. // -------------------------------------------------------
  362. TDOMEntityReference = class(TDOMNode_WithChildren)
  363. protected
  364. constructor Create(AOwner: TDOMDocument);
  365. end;
  366. // -------------------------------------------------------
  367. // ProcessingInstruction
  368. // -------------------------------------------------------
  369. TDOMProcessingInstruction = class(TDOMNode)
  370. protected
  371. constructor Create(AOwner: TDOMDocument);
  372. public
  373. property Target: DOMString read FNodeName;
  374. property Data: DOMString read FNodeValue;
  375. end;
  376. // =======================================================
  377. // =======================================================
  378. implementation
  379. constructor TRefClass.Create;
  380. begin
  381. inherited Create;
  382. RefCounter := 1;
  383. end;
  384. function TRefClass.AddRef: LongInt;
  385. begin
  386. Inc(RefCounter);
  387. Result := RefCounter;
  388. end;
  389. function TRefClass.Release: LongInt;
  390. begin
  391. Dec(RefCounter);
  392. Result := RefCounter;
  393. if RefCounter <= 0 then Free;
  394. end;
  395. // -------------------------------------------------------
  396. // DOM Exception
  397. // -------------------------------------------------------
  398. constructor EDOMError.Create(ACode: Integer; const ASituation: String);
  399. begin
  400. Code := ACode;
  401. inherited Create(Self.ClassName + ' in ' + ASituation);
  402. end;
  403. constructor EDOMIndexSize.Create(const ASituation: String); // 1
  404. begin
  405. inherited Create(INDEX_SIZE_ERR, ASituation);
  406. end;
  407. constructor EDOMHierarchyRequest.Create(const ASituation: String); // 3
  408. begin
  409. inherited Create(HIERARCHY_REQUEST_ERR, ASituation);
  410. end;
  411. constructor EDOMWrongDocument.Create(const ASituation: String); // 4
  412. begin
  413. inherited Create(WRONG_DOCUMENT_ERR, ASituation);
  414. end;
  415. constructor EDOMNotFound.Create(const ASituation: String); // 8
  416. begin
  417. inherited Create(NOT_FOUND_ERR, ASituation);
  418. end;
  419. constructor EDOMNotSupported.Create(const ASituation: String); // 9
  420. begin
  421. inherited Create(NOT_SUPPORTED_ERR, ASituation);
  422. end;
  423. constructor EDOMInUseAttribute.Create(const ASituation: String); // 10
  424. begin
  425. inherited Create(INUSE_ATTRIBUTE_ERR, ASituation);
  426. end;
  427. // -------------------------------------------------------
  428. // Node
  429. // -------------------------------------------------------
  430. constructor TDOMNode.Create(AOwner: TDOMDocument);
  431. begin
  432. FOwnerDocument := AOwner;
  433. inherited Create;
  434. end;
  435. function TDOMNode.GetNodeValue: DOMString;
  436. begin
  437. Result := FNodeValue;
  438. end;
  439. procedure TDOMNode.SetNodeValue(AValue: DOMString);
  440. begin
  441. FNodeValue := AValue;
  442. end;
  443. function TDOMNode.GetChildNodes: TDOMNodeList;
  444. begin
  445. Result := TDOMNodeList.Create(Self, '*');
  446. end;
  447. function TDOMNode.GetFirstChild: TDOMNode; begin Result := nil end;
  448. function TDOMNode.GetLastChild: TDOMNode; begin Result := nil end;
  449. function TDOMNode.GetAttributes: TDOMNamedNodeMap; begin Result := nil end;
  450. function TDOMNode.InsertBefore(NewChild, RefChild: TDOMNode): TDOMNode;
  451. begin
  452. raise EDOMHierarchyRequest.Create('Node.InsertBefore');
  453. end;
  454. function TDOMNode.ReplaceChild(NewChild, OldChild: TDOMNode): TDOMNode;
  455. begin
  456. raise EDOMHierarchyRequest.Create('Node.ReplaceChild');
  457. end;
  458. function TDOMNode.RemoveChild(OldChild: TDOMNode): TDOMNode;
  459. begin
  460. raise EDOMHierarchyRequest.Create('Node.RemoveChild');
  461. end;
  462. function TDOMNode.AppendChild(NewChild: TDOMNode): TDOMNode;
  463. begin
  464. raise EDOMHierarchyRequest.Create('Node.AppendChild');
  465. end;
  466. function TDOMNode.HasChildNodes: Boolean;
  467. begin
  468. Result := False;
  469. end;
  470. function TDOMNode.CloneNode(deep: Boolean): TDOMNode;
  471. begin
  472. Result := nil;
  473. end;
  474. function TDOMNode.FindNode(const ANodeName: DOMString): TDOMNode;
  475. var
  476. child: TDOMNode;
  477. begin
  478. child := FirstChild;
  479. while Assigned(child) do begin
  480. if child.NodeName = ANodeName then begin
  481. Result := child;
  482. exit;
  483. end;
  484. child := child.NextSibling;
  485. end;
  486. Result := nil;
  487. end;
  488. function TDOMNode_WithChildren.GetFirstChild: TDOMNode;
  489. begin
  490. Result := FFirstChild;
  491. end;
  492. function TDOMNode_WithChildren.GetLastChild: TDOMNode;
  493. begin
  494. Result := FLastChild;
  495. end;
  496. destructor TDOMNode_WithChildren.Destroy;
  497. var
  498. child, next: TDOMNode;
  499. begin
  500. child := FirstChild;
  501. while Assigned(child) do begin
  502. next := child.NextSibling;
  503. child.Free;
  504. child := next;
  505. end;
  506. inherited Destroy;
  507. end;
  508. function TDOMNode_WithChildren.InsertBefore(NewChild, RefChild: TDOMNode):
  509. TDOMNode;
  510. var
  511. i: Integer;
  512. begin
  513. if not Assigned(RefChild) then begin
  514. AppendChild(NewChild);
  515. exit(NewChild);
  516. end;
  517. if NewChild.FOwnerDocument <> FOwnerDocument then
  518. raise EDOMWrongDocument.Create('NodeWC.InsertBefore');
  519. if RefChild.ParentNode <> Self then
  520. raise EDOMHierarchyRequest.Create('NodeWC.InsertBefore');
  521. if NewChild.NodeType = DOCUMENT_FRAGMENT_NODE then
  522. raise EDOMNotSupported.Create('NodeWC.InsertBefore for DocumentFragment');
  523. NewChild.FNextSibling := RefChild;
  524. if RefChild = FFirstChild then
  525. FFirstChild := NewChild
  526. else
  527. RefChild.FPreviousSibling.FNextSibling := NewChild;
  528. RefChild.FPreviousSibling := NewChild;
  529. Result := NewChild;
  530. end;
  531. function TDOMNode_WithChildren.ReplaceChild(NewChild, OldChild: TDOMNode):
  532. TDOMNode;
  533. begin
  534. InsertBefore(NewChild, OldChild);
  535. if Assigned(OldChild) then
  536. RemoveChild(OldChild);
  537. Result := NewChild;
  538. end;
  539. function TDOMNode_WithChildren.RemoveChild(OldChild: TDOMNode):
  540. TDOMNode;
  541. begin
  542. if OldChild.ParentNode <> Self then
  543. raise EDOMHierarchyRequest.Create('NodeWC.RemoveChild');
  544. if OldChild = FFirstChild then
  545. FFirstChild := nil
  546. else
  547. OldChild.FPreviousSibling.FNextSibling := OldChild.FNextSibling;
  548. if OldChild = FLastChild then
  549. FLastChild := nil
  550. else
  551. OldChild.FNextSibling.FPreviousSibling := OldChild.FPreviousSibling;
  552. OldChild.Free;
  553. end;
  554. function TDOMNode_WithChildren.AppendChild(NewChild: TDOMNode): TDOMNode;
  555. var
  556. parent: TDOMNode;
  557. begin
  558. if NewChild.FOwnerDocument <> FOwnerDocument then
  559. raise EDOMWrongDocument.Create('NodeWC.AppendChild');
  560. parent := Self;
  561. while Assigned(parent) do begin
  562. if parent = NewChild then
  563. raise EDOMHierarchyRequest.Create('NodeWC.AppendChild (cycle in tree)');
  564. parent := parent.ParentNode;
  565. end;
  566. if NewChild.FParentNode = Self then
  567. RemoveChild(NewChild);
  568. if NewChild.NodeType = DOCUMENT_FRAGMENT_NODE then
  569. raise EDOMNotSupported.Create('NodeWC.AppendChild for DocumentFragments')
  570. else begin
  571. if Assigned(FFirstChild) then begin
  572. FLastChild.FNextSibling := NewChild;
  573. NewChild.FPreviousSibling := FLastChild;
  574. end else
  575. FFirstChild := NewChild;
  576. FLastChild := NewChild;
  577. NewChild.FParentNode := Self;
  578. end;
  579. Result := NewChild;
  580. end;
  581. function TDOMNode_WithChildren.HasChildNodes: Boolean;
  582. begin
  583. Result := Assigned(FFirstChild);
  584. end;
  585. // -------------------------------------------------------
  586. // NodeList
  587. // -------------------------------------------------------
  588. constructor TDOMNodeList.Create(ANode: TDOMNode; AFilter: DOMString);
  589. begin
  590. inherited Create;
  591. node := ANode;
  592. filter := AFilter;
  593. UseFilter := filter <> '*';
  594. end;
  595. function TDOMNodeList.GetCount: LongWord;
  596. var
  597. child: TDOMNode;
  598. begin
  599. Result := 0;
  600. child := node.FirstChild;
  601. while Assigned(child) do begin
  602. if (not UseFilter) or (child.NodeName = filter) then
  603. Inc(Result);
  604. child := child.NextSibling;
  605. end;
  606. end;
  607. function TDOMNodeList.GetItem(index: LongWord): TDOMNode;
  608. var
  609. child: TDOMNode;
  610. begin
  611. Result := nil;
  612. if index < 0 then exit;
  613. child := node.FirstChild;
  614. while Assigned(child) do begin
  615. if index = 0 then begin
  616. Result := child;
  617. break;
  618. end;
  619. if (not UseFilter) or (child.NodeName = filter) then
  620. Dec(index);
  621. child := child.NextSibling;
  622. end;
  623. end;
  624. // -------------------------------------------------------
  625. // NamedNodeMap
  626. // -------------------------------------------------------
  627. constructor TDOMNamedNodeMap.Create(AOwner: TDOMDocument);
  628. begin
  629. inherited Create;
  630. OwnerDocument := AOwner;
  631. end;
  632. function TDOMNamedNodeMap.GetItem(index: LongWord): TDOMNode;
  633. begin
  634. Result := TDOMNode(Items[index]);
  635. end;
  636. procedure TDOMNamedNodeMap.SetItem(index: LongWord; AItem: TDOMNode);
  637. begin
  638. Items[index] := AItem;
  639. end;
  640. function TDOMNamedNodeMap.GetLength: LongWord;
  641. begin
  642. Result := LongWord(Count);
  643. end;
  644. function TDOMNamedNodeMap.GetNamedItem(const name: DOMString): TDOMNode;
  645. var
  646. i: Integer;
  647. begin
  648. for i := 0 to Count - 1 do
  649. if Item[i].NodeName = name then
  650. exit(Item[i]);
  651. Result := nil;
  652. end;
  653. function TDOMNamedNodeMap.SetNamedItem(arg: TDOMNode): TDOMNode;
  654. var
  655. i: Integer;
  656. begin
  657. if arg.FOwnerDocument <> OwnerDocument then
  658. raise EDOMWrongDocument.Create('NamedNodeMap.SetNamedItem');
  659. if arg.NodeType = ATTRIBUTE_NODE then begin
  660. if Assigned(TDOMAttr(arg).AttrOwner) then
  661. raise EDOMInUseAttribute.Create('NamedNodeMap.SetNamedItem');
  662. TDOMAttr(arg).AttrOwner := Self;
  663. end;
  664. for i := 0 to Count - 1 do
  665. if Item[i].NodeName = arg.NodeName then begin
  666. Result := Item[i];
  667. Item[i] := arg;
  668. exit;
  669. end;
  670. Add(arg);
  671. Result := nil;
  672. end;
  673. function TDOMNamedNodeMap.RemoveNamedItem(const name: DOMString): TDOMNode;
  674. var
  675. i: Integer;
  676. begin
  677. for i := 0 to Count - 1 do
  678. if Item[i].NodeName = name then begin
  679. Result := Item[i];
  680. Result.FParentNode := nil;
  681. exit;
  682. end;
  683. raise EDOMNotFound.Create('NamedNodeMap.RemoveNamedItem');
  684. end;
  685. // -------------------------------------------------------
  686. // CharacterData
  687. // -------------------------------------------------------
  688. function TDOMCharacterData.GetLength: LongWord;
  689. begin
  690. Result := system.Length(FNodeValue);
  691. end;
  692. function TDOMCharacterData.SubstringData(offset, count: LongWord): DOMString;
  693. begin
  694. if (offset < 0) or (offset > Length) or (count < 0) then
  695. raise EDOMIndexSize.Create('CharacterData.SubstringData');
  696. Result := Copy(FNodeValue, offset + 1, count);
  697. end;
  698. procedure TDOMCharacterData.AppendData(const arg: DOMString);
  699. begin
  700. FNodeValue := FNodeValue + arg;
  701. end;
  702. procedure TDOMCharacterData.InsertData(offset: LongWord; const arg: DOMString);
  703. begin
  704. if (offset < 0) or (offset > Length) then
  705. raise EDOMIndexSize.Create('CharacterData.InsertData');
  706. FNodeValue := Copy(FNodeValue, 1, offset) + arg +
  707. Copy(FNodeValue, offset + 1, Length);
  708. end;
  709. procedure TDOMCharacterData.DeleteData(offset, count: LongWord);
  710. begin
  711. if (offset < 0) or (offset > Length) or (count < 0) then
  712. raise EDOMIndexSize.Create('CharacterData.DeleteData');
  713. FNodeValue := Copy(FNodeValue, 1, offset) +
  714. Copy(FNodeValue, offset + count + 1, Length);
  715. end;
  716. procedure TDOMCharacterData.ReplaceData(offset, count: LongWord; const arg: DOMString);
  717. begin
  718. DeleteData(offset, count);
  719. InsertData(offset, arg);
  720. end;
  721. // -------------------------------------------------------
  722. // DocumentFragmet
  723. // -------------------------------------------------------
  724. constructor TDOMDocumentFragment.Create(AOwner: TDOMDocument);
  725. begin
  726. FNodeType := DOCUMENT_FRAGMENT_NODE;
  727. FNodeName := '#document-fragment';
  728. inherited Create(AOwner);
  729. end;
  730. // -------------------------------------------------------
  731. // DOMImplementation
  732. // -------------------------------------------------------
  733. function TDOMImplementation.HasFeature(const feature, version: DOMString):
  734. Boolean;
  735. begin
  736. Result := False;
  737. end;
  738. // -------------------------------------------------------
  739. // Document
  740. // -------------------------------------------------------
  741. constructor TDOMDocument.Create;
  742. begin
  743. FNodeType := DOCUMENT_NODE;
  744. FNodeName := '#document';
  745. inherited Create(nil);
  746. FOwnerDocument := Self;
  747. end;
  748. function TDOMDocument.GetDocumentElement: TDOMElement;
  749. var
  750. node: TDOMNode;
  751. begin
  752. node := FFirstChild;
  753. while Assigned(node) do begin
  754. if node.FNodeType = ELEMENT_NODE then begin
  755. Result := TDOMElement(node);
  756. exit;
  757. end;
  758. node := node.NextSibling;
  759. end;
  760. Result := nil;
  761. end;
  762. function TDOMDocument.CreateElement(const tagName: DOMString): TDOMElement;
  763. begin
  764. Result := TDOMElement.Create(Self);
  765. Result.FNodeName := tagName;
  766. end;
  767. function TDOMDocument.CreateDocumentFragment: TDOMDocumentFragment;
  768. begin
  769. Result := TDOMDocumentFragment.Create(Self);
  770. end;
  771. function TDOMDocument.CreateTextNode(const data: DOMString): TDOMText;
  772. begin
  773. Result := TDOMText.Create(Self);
  774. Result.FNodeValue := data;
  775. end;
  776. function TDOMDocument.CreateComment(const data: DOMString): TDOMComment;
  777. begin
  778. Result := TDOMComment.Create(Self);
  779. Result.FNodeValue := data;
  780. end;
  781. function TDOMDocument.CreateCDATASection(const data: DOMString):
  782. TDOMCDATASection;
  783. begin
  784. raise EDOMNotSupported.Create('DOMDocument.CreateCDATASection');
  785. end;
  786. function TDOMDocument.CreateProcessingInstruction(const target,
  787. data: DOMString): TDOMProcessingInstruction;
  788. begin
  789. raise EDOMNotSupported.Create('DOMDocument.CreateProcessingInstruction');
  790. end;
  791. function TDOMDocument.CreateAttribute(const name: DOMString): TDOMAttr;
  792. begin
  793. Result := TDOMAttr.Create(Self);
  794. Result.FNodeName := name;
  795. end;
  796. function TDOMDocument.CreateEntityReference(const name: DOMString):
  797. TDOMEntityReference;
  798. begin
  799. raise EDOMNotSupported.Create('DOMDocument.CreateEntityReference');
  800. end;
  801. function TDOMDocument.CreateEntity(const data: DOMString): TDOMEntity;
  802. begin
  803. Result := TDOMEntity.Create(Self);
  804. Result.FNodeValue := data;
  805. end;
  806. function TDOMDocument.GetElementsByTagName(const tagname: DOMString): TDOMNodeList;
  807. begin
  808. Result := TDOMNodeList.Create(Self, tagname);
  809. end;
  810. function TXMLDocument.CreateCDATASection(const data: DOMString):
  811. TDOMCDATASection;
  812. begin
  813. Result := TDOMCDATASection.Create(Self);
  814. Result.FNodeValue := data;
  815. end;
  816. function TXMLDocument.CreateProcessingInstruction(const target,
  817. data: DOMString): TDOMProcessingInstruction;
  818. begin
  819. Result := TDOMProcessingInstruction.Create(Self);
  820. Result.FNodeName := target;
  821. Result.FNodeValue := data;
  822. end;
  823. function TXMLDocument.CreateEntityReference(const name: DOMString):
  824. TDOMEntityReference;
  825. begin
  826. Result := TDOMEntityReference.Create(Self);
  827. Result.FNodeName := name;
  828. end;
  829. // -------------------------------------------------------
  830. // Attr
  831. // -------------------------------------------------------
  832. constructor TDOMAttr.Create(AOwner: TDOMDocument);
  833. begin
  834. FNodeType := ATTRIBUTE_NODE;
  835. inherited Create(AOwner);
  836. end;
  837. function TDOMAttr.GetNodeValue: DOMString;
  838. var
  839. child: TDOMNode;
  840. begin
  841. SetLength(Result, 0);
  842. if Assigned(FFirstChild) then begin
  843. child := FFirstChild;
  844. while Assigned(child) do begin
  845. if child.NodeType = ENTITY_REFERENCE_NODE then
  846. Result := Result + '&' + child.NodeName + ';'
  847. else
  848. Result := Result + child.NodeValue;
  849. child := child.NextSibling;
  850. end;
  851. end;
  852. end;
  853. procedure TDOMAttr.SetNodeValue(AValue: DOMString);
  854. var
  855. tn: TDOMText;
  856. begin
  857. FSpecified := True;
  858. tn := TDOMText.Create(FOwnerDocument);
  859. tn.FNodeValue := AValue;
  860. if Assigned(FFirstChild) then
  861. ReplaceChild(tn, FFirstChild)
  862. else
  863. AppendChild(tn);
  864. end;
  865. // -------------------------------------------------------
  866. // Element
  867. // -------------------------------------------------------
  868. constructor TDOMElement.Create(AOwner: TDOMDocument);
  869. begin
  870. FNodeType := ELEMENT_NODE;
  871. inherited Create(AOwner);
  872. FAttributes := TDOMNamedNodeMap.Create(AOwner);
  873. end;
  874. destructor TDOMElement.Destroy;
  875. var
  876. i: Integer;
  877. begin
  878. {As the attributes are _not_ childs of the element node, we have to free
  879. them manually here:}
  880. for i := 0 to FAttributes.Count - 1 do
  881. FAttributes.Item[i].Free;
  882. FAttributes.Free;
  883. inherited Destroy;
  884. end;
  885. function TDOMElement.GetAttributes: TDOMNamedNodeMap;
  886. begin
  887. Result := FAttributes;
  888. end;
  889. function TDOMElement.GetAttribute(const name: DOMString): DOMString;
  890. var
  891. i: Integer;
  892. begin
  893. for i := 0 to FAttributes.Count - 1 do
  894. if FAttributes.Item[i].NodeName = name then begin
  895. Result := FAttributes.Item[i].NodeValue;
  896. exit;
  897. end;
  898. SetLength(Result, 0);
  899. end;
  900. procedure TDOMElement.SetAttribute(const name, value: DOMString);
  901. var
  902. i: Integer;
  903. attr: TDOMAttr;
  904. begin
  905. for i := 0 to FAttributes.Count - 1 do
  906. if FAttributes.Item[i].NodeName = name then begin
  907. FAttributes.Item[i].NodeValue := value;
  908. exit;
  909. end;
  910. attr := TDOMAttr.Create(FOwnerDocument);
  911. attr.FNodeName := name;
  912. attr.NodeValue := value;
  913. FAttributes.Add(attr);
  914. end;
  915. procedure TDOMElement.RemoveAttribute(const name: DOMString);
  916. var
  917. i: Integer;
  918. begin
  919. for i := 0 to FAttributes.Count - 1 do
  920. if FAttributes.Item[i].NodeName = name then begin
  921. FAttributes.Delete(i);
  922. FAttributes.Item[i].Free;
  923. exit;
  924. end;
  925. end;
  926. function TDOMElement.GetAttributeNode(const name: DOMString): TDOMAttr;
  927. var
  928. i: Integer;
  929. begin
  930. for i := 0 to FAttributes.Count - 1 do
  931. if FAttributes.Item[i].NodeName = name then
  932. exit(TDOMAttr(FAttributes.Item[i]));
  933. Result := nil;
  934. end;
  935. procedure TDOMElement.SetAttributeNode(NewAttr: TDOMAttr);
  936. var
  937. i: Integer;
  938. begin
  939. for i := 0 to FAttributes.Count - 1 do
  940. if FAttributes.Item[i].NodeName = NewAttr.NodeName then begin
  941. FAttributes.Item[i].Free;
  942. FAttributes.Item[i] := NewAttr;
  943. exit;
  944. end;
  945. end;
  946. function TDOMElement.RemoveAttributeNode(OldAttr: TDOMAttr): TDOMAttr;
  947. var
  948. i: Integer;
  949. node: TDOMNode;
  950. begin
  951. for i := 0 to FAttributes.Count - 1 do begin
  952. node := FAttributes.Item[i];
  953. if node = OldAttr then begin
  954. FAttributes.Delete(i);
  955. exit(TDOMAttr(node));
  956. end;
  957. end;
  958. end;
  959. function TDOMElement.GetElementsByTagName(const name: DOMString): TDOMNodeList;
  960. begin
  961. Result := TDOMNodeList.Create(Self, name);
  962. end;
  963. procedure TDOMElement.Normalize;
  964. begin
  965. end;
  966. // -------------------------------------------------------
  967. // Text
  968. // -------------------------------------------------------
  969. constructor TDOMText.Create(AOwner: TDOMDocument);
  970. begin
  971. FNodeType := TEXT_NODE;
  972. FNodeName := '#text';
  973. inherited Create(AOwner);
  974. end;
  975. function TDOMText.SplitText(offset: LongWord): TDOMText;
  976. var
  977. nt: TDOMText;
  978. begin
  979. if offset > Length then
  980. raise EDOMIndexSize.Create('Text.SplitText');
  981. nt := TDOMText.Create(FOwnerDocument);
  982. nt.FNodeValue := Copy(FNodeValue, offset + 1, Length);
  983. FNodeValue := Copy(FNodeValue, 1, offset);
  984. FParentNode.InsertBefore(nt, FNextSibling);
  985. end;
  986. // -------------------------------------------------------
  987. // Comment
  988. // -------------------------------------------------------
  989. constructor TDOMComment.Create(AOwner: TDOMDocument);
  990. begin
  991. FNodeType := COMMENT_NODE;
  992. FNodeName := '#comment';
  993. inherited Create(AOwner);
  994. end;
  995. // -------------------------------------------------------
  996. // CDATASection
  997. // -------------------------------------------------------
  998. constructor TDOMCDATASection.Create(AOwner: TDOMDocument);
  999. begin
  1000. inherited Create(AOwner);
  1001. FNodeType := CDATA_SECTION_NODE;
  1002. FNodeName := '#cdata-section';
  1003. end;
  1004. // -------------------------------------------------------
  1005. // DocumentType
  1006. // -------------------------------------------------------
  1007. constructor TDOMDocumentType.Create(AOwner: TDOMDocument);
  1008. begin
  1009. FNodeType := DOCUMENT_TYPE_NODE;
  1010. inherited Create(AOwner);
  1011. end;
  1012. // -------------------------------------------------------
  1013. // Notation
  1014. // -------------------------------------------------------
  1015. constructor TDOMNotation.Create(AOwner: TDOMDocument);
  1016. begin
  1017. FNodeType := NOTATION_NODE;
  1018. inherited Create(AOwner);
  1019. end;
  1020. // -------------------------------------------------------
  1021. // Entity
  1022. // -------------------------------------------------------
  1023. constructor TDOMEntity.Create(AOwner: TDOMDocument);
  1024. begin
  1025. FNodeType := ENTITY_NODE;
  1026. inherited Create(AOwner);
  1027. end;
  1028. // -------------------------------------------------------
  1029. // EntityReference
  1030. // -------------------------------------------------------
  1031. constructor TDOMEntityReference.Create(AOwner: TDOMDocument);
  1032. begin
  1033. FNodeType := ENTITY_REFERENCE_NODE;
  1034. inherited Create(AOwner);
  1035. end;
  1036. // -------------------------------------------------------
  1037. // ProcessingInstruction
  1038. // -------------------------------------------------------
  1039. constructor TDOMProcessingInstruction.Create(AOwner: TDOMDocument);
  1040. begin
  1041. FNodeType := PROCESSING_INSTRUCTION_NODE;
  1042. inherited Create(AOwner);
  1043. end;
  1044. end.
  1045. {
  1046. $Log$
  1047. Revision 1.12 2000-02-13 10:03:31 sg
  1048. * Hopefully final fix for TDOMDocument.DocumentElement:
  1049. - Reading this property always delivers the first element in the document
  1050. - Removed SetDocumentElement. Use "AppendChild" or one of the other
  1051. generic methods for TDOMNode instead.
  1052. Revision 1.11 2000/01/30 22:18:16 sg
  1053. * Fixed memory leaks, all nodes are now freed by their parent
  1054. * Many cosmetic changes
  1055. Revision 1.10 2000/01/07 01:24:34 peter
  1056. * updated copyright to 2000
  1057. Revision 1.9 2000/01/06 23:55:22 peter
  1058. * childnodes property as that is used instead of getchildnodes
  1059. in the apps
  1060. Revision 1.8 2000/01/06 01:20:36 peter
  1061. * moved out of packages/ back to topdir
  1062. Revision 1.1 2000/01/03 19:33:11 peter
  1063. * moved to packages dir
  1064. Revision 1.6 1999/12/05 22:00:10 sg
  1065. * Bug workaround for problem with "exit(<some string type>)"
  1066. Revision 1.5 1999/07/12 12:19:49 michael
  1067. + More fixes from Sebastian Guenther
  1068. Revision 1.4 1999/07/11 20:20:11 michael
  1069. + Fixes from Sebastian Guenther
  1070. Revision 1.3 1999/07/10 21:48:26 michael
  1071. + Made domelement constructor virtual, needs overriding in thtmlelement
  1072. Revision 1.2 1999/07/09 21:05:49 michael
  1073. + fixes from Guenther Sebastian
  1074. Revision 1.1 1999/07/09 08:35:09 michael
  1075. + Initial implementation by Sebastian Guenther
  1076. }