dom.pp 33 KB

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