mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-10-31 09:41:39 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			1695 lines
		
	
	
		
			46 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			1695 lines
		
	
	
		
			46 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
| {
 | |
|   BEWARE !!!
 | |
|   This is a TEMPORARY file.
 | |
|   As soon as it is moved to the fcl, it will be removed.
 | |
| }
 | |
| 
 | |
| {
 | |
|     $Id$
 | |
|     This file is part of the Free Component Library
 | |
| 
 | |
|     Implementation of DOM interfaces
 | |
|     Copyright (c) 1999-2000 by Sebastian Guenther, sg@freepascal.org
 | |
| 
 | |
|     See the file COPYING.modifiedLGPL, included in this distribution,
 | |
|     for details about the copyright.
 | |
| 
 | |
|     This program is distributed in the hope that it will be useful,
 | |
|     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 | |
| 
 | |
|  **********************************************************************}
 | |
| 
 | |
| {
 | |
|   This unit provides classes which implement the interfaces defined in the
 | |
|   DOM (Document Object Model) specification.
 | |
|   The current state is:
 | |
|   DOM Level 1  -  Almost completely implemented
 | |
|   DOM Level 2  -  Partially implemented
 | |
| 
 | |
| 
 | |
|   Specification used for this implementation:
 | |
| 
 | |
|   "Document Object Model (DOM) Level 2 Specification Version 1.0
 | |
|    W3C Candidate Recommendation 07 March, 2000"
 | |
|   http://www.w3.org/TR/2000/CR-DOM-Level-2-20000307
 | |
| }
 | |
| 
 | |
| 
 | |
| unit Laz_DOM;
 | |
| 
 | |
| {$MODE objfpc}
 | |
| {$H+}
 | |
| 
 | |
| interface
 | |
| 
 | |
| {off $DEFINE MEM_CHECK}
 | |
| 
 | |
| uses
 | |
|   {$IFDEF MEM_CHECK}MemCheck,{$ENDIF}
 | |
|   SysUtils, Classes, Avl_Tree;
 | |
| 
 | |
| 
 | |
| type
 | |
|   TDOMImplementation = class;
 | |
|   TDOMDocumentFragment = class;
 | |
|   TDOMDocument = class;
 | |
|   TDOMNode = class;
 | |
|   TDOMNodeList = class;
 | |
|   TDOMNamedNodeMap = class;
 | |
|   TDOMCharacterData = class;
 | |
|   TDOMAttr = class;
 | |
|   TDOMElement = class;
 | |
|   TDOMText = class;
 | |
|   TDOMComment = class;
 | |
|   TDOMCDATASection = class;
 | |
|   TDOMDocumentType = class;
 | |
|   TDOMNotation = class;
 | |
|   TDOMEntity = class;
 | |
|   TDOMEntityReference = class;
 | |
|   TDOMProcessingInstruction = class;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   DOMString
 | |
| // -------------------------------------------------------
 | |
|   DOMString = String;
 | |
|   DOMPChar = PChar;
 | |
| //  DOMString = WideString;
 | |
| //  DOMPChar = PWideChar;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   DOMException
 | |
| // -------------------------------------------------------
 | |
| 
 | |
| 
 | |
| const
 | |
| 
 | |
|   // DOM Level 1 exception codes:
 | |
| 
 | |
|   INDEX_SIZE_ERR              = 1;  // index or size is negative, or greater than the allowed value
 | |
|   DOMSTRING_SIZE_ERR          = 2;  // Specified range of text does not fit into a DOMString
 | |
|   HIERARCHY_REQUEST_ERR       = 3;  // node is inserted somewhere it does not belong
 | |
|   WRONG_DOCUMENT_ERR          = 4;  // node is used in a different document than the one that created it (that does not support it)
 | |
|   INVALID_CHARACTER_ERR       = 5;  // invalid or illegal character is specified, such as in a name
 | |
|   NO_DATA_ALLOWED_ERR         = 6;  // data is specified for a node which does not support data
 | |
|   NO_MODIFICATION_ALLOWED_ERR = 7;  // an attempt is made to modify an object where modifications are not allowed
 | |
|   NOT_FOUND_ERR               = 8;  // an attempt is made to reference a node in a context where it does not exist
 | |
|   NOT_SUPPORTED_ERR           = 9;  // implementation does not support the type of object requested
 | |
|   INUSE_ATTRIBUTE_ERR         = 10;  // an attempt is made to add an attribute that is already in use elsewhere
 | |
| 
 | |
|   // DOM Level 2 exception codes:
 | |
| 
 | |
|   INVALID_STATE_ERR           = 11;  // an attempt is made to use an object that is not, or is no longer, usable
 | |
|   SYNTAX_ERR                  = 12;  // invalid or illegal string specified
 | |
|   INVALID_MODIFICATION_ERR    = 13;  // an attempt is made to modify the type of the underlying object
 | |
|   NAMESPACE_ERR               = 14;  // an attempt is made to create or change an object in a way which is incorrect with regard to namespaces
 | |
|   INVALID_ACCESS_ERR          = 15;  // parameter or operation is not supported by the underlying object
 | |
| 
 | |
| 
 | |
| type
 | |
| 
 | |
|   EDOMError = class(Exception)
 | |
|   public
 | |
|     constructor Create(ACode: Integer; const ASituation: String);
 | |
|     Code: Integer;
 | |
|   end;
 | |
| 
 | |
|   EDOMIndexSize = class(EDOMError)
 | |
|   public
 | |
|     constructor Create(const ASituation: String);
 | |
|   end;
 | |
| 
 | |
|   EDOMHierarchyRequest = class(EDOMError)
 | |
|   public
 | |
|     constructor Create(const ASituation: String);
 | |
|   end;
 | |
| 
 | |
|   EDOMWrongDocument = class(EDOMError)
 | |
|   public
 | |
|     constructor Create(const ASituation: String);
 | |
|   end;
 | |
| 
 | |
|   EDOMNotFound = class(EDOMError)
 | |
|   public
 | |
|     constructor Create(const ASituation: String);
 | |
|   end;
 | |
| 
 | |
|   EDOMNotSupported = class(EDOMError)
 | |
|   public
 | |
|     constructor Create(const ASituation: String);
 | |
|   end;
 | |
| 
 | |
|   EDOMInUseAttribute = class(EDOMError)
 | |
|   public
 | |
|     constructor Create(const ASituation: String);
 | |
|   end;
 | |
| 
 | |
|   EDOMInvalidState = class(EDOMError)
 | |
|   public
 | |
|     constructor Create(const ASituation: String);
 | |
|   end;
 | |
| 
 | |
|   EDOMSyntax = class(EDOMError)
 | |
|   public
 | |
|     constructor Create(const ASituation: String);
 | |
|   end;
 | |
| 
 | |
|   EDOMInvalidModification = class(EDOMError)
 | |
|   public
 | |
|     constructor Create(const ASituation: String);
 | |
|   end;
 | |
| 
 | |
|   EDOMNamespace = class(EDOMError)
 | |
|   public
 | |
|     constructor Create(const ASituation: String);
 | |
|   end;
 | |
| 
 | |
|   EDOMInvalidAccess = class(EDOMError)
 | |
|   public
 | |
|     constructor Create(const ASituation: String);
 | |
|   end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   Node
 | |
| // -------------------------------------------------------
 | |
| 
 | |
| const
 | |
| 
 | |
|   ELEMENT_NODE = 1;
 | |
|   ATTRIBUTE_NODE = 2;
 | |
|   TEXT_NODE = 3;
 | |
|   CDATA_SECTION_NODE = 4;
 | |
|   ENTITY_REFERENCE_NODE = 5;
 | |
|   ENTITY_NODE = 6;
 | |
|   PROCESSING_INSTRUCTION_NODE = 7;
 | |
|   COMMENT_NODE = 8;
 | |
|   DOCUMENT_NODE = 9;
 | |
|   DOCUMENT_TYPE_NODE = 10;
 | |
|   DOCUMENT_FRAGMENT_NODE = 11;
 | |
|   NOTATION_NODE = 12;
 | |
| 
 | |
| 
 | |
| type
 | |
| 
 | |
|   TRefClass = class
 | |
|   protected
 | |
|     RefCounter: LongInt;
 | |
|   public
 | |
|     constructor Create;
 | |
|     function AddRef: LongInt; virtual;
 | |
|     function Release: LongInt; virtual;
 | |
|   end;
 | |
| 
 | |
|   { TDOMNode }
 | |
| 
 | |
|   TDOMNode = class
 | |
|   protected
 | |
|     FNodeName, FNodeValue: DOMString;
 | |
|     FNodeType: Integer;
 | |
|     FParentNode: TDOMNode;
 | |
|     FPreviousSibling, FNextSibling: TDOMNode;
 | |
|     FOwnerDocument: TDOMDocument;
 | |
| 
 | |
|     function  GetNodeValue: DOMString; virtual;
 | |
|     procedure SetNodeValue(const AValue: DOMString); virtual;
 | |
|     function  GetFirstChild: TDOMNode; virtual;
 | |
|     function  GetLastChild: TDOMNode; virtual;
 | |
|     function  GetAttributes: TDOMNamedNodeMap; virtual;
 | |
| 
 | |
|   public
 | |
|     constructor Create(AOwner: TDOMDocument);
 | |
|     
 | |
|     // Free NodeList with TDOMNodeList.Release!
 | |
|     function GetChildNodes: TDOMNodeList; virtual;
 | |
| 
 | |
|     property NodeName: DOMString read FNodeName;
 | |
|     property NodeValue: DOMString read GetNodeValue write SetNodeValue;
 | |
|     property NodeType: Integer read FNodeType;
 | |
|     property ParentNode: TDOMNode read FParentNode;
 | |
|     property FirstChild: TDOMNode read GetFirstChild;
 | |
|     property LastChild: TDOMNode read GetLastChild;
 | |
|     property ChildNodes: TDOMNodeList read GetChildNodes;
 | |
|     property PreviousSibling: TDOMNode read FPreviousSibling;
 | |
|     property NextSibling: TDOMNode read FNextSibling;
 | |
|     property Attributes: TDOMNamedNodeMap read GetAttributes;
 | |
|     property OwnerDocument: TDOMDocument read FOwnerDocument;
 | |
| 
 | |
|     function InsertBefore(NewChild, RefChild: TDOMNode): TDOMNode; virtual;
 | |
|     function ReplaceChild(NewChild, OldChild: TDOMNode): TDOMNode; virtual;
 | |
|     function RemoveChild(OldChild: TDOMNode): TDOMNode; virtual;
 | |
|     function AppendChild(NewChild: TDOMNode): TDOMNode; virtual;
 | |
|     function HasChildNodes: Boolean; virtual;
 | |
|     function CloneNode(deep: Boolean): TDOMNode; overload;
 | |
|     function IsEmpty: Boolean; virtual;
 | |
| 
 | |
|     // Extensions to DOM interface:
 | |
|     function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; virtual;
 | |
|     function FindNode(const ANodeName: DOMString): TDOMNode; virtual;
 | |
|   end;
 | |
| 
 | |
| 
 | |
|   { The following class is an implementation specific extension, it is just an
 | |
|     extended implementation of TDOMNode, the generic DOM::Node interface
 | |
|     implementation. (Its main purpose is to save memory in a big node tree) }
 | |
| 
 | |
|   TDOMNode_WithChildren = class(TDOMNode)
 | |
|   protected
 | |
|     FFirstChild, FLastChild: TDOMNode;
 | |
|     FChildNodeTree: TAVLTree;// tree of TDOMNode sorted for Name (=> there can be doubles)
 | |
|     function GetFirstChild: TDOMNode; override;
 | |
|     function GetLastChild: TDOMNode; override;
 | |
|     procedure CloneChildren(ACopy: TDOMNode; ACloneOwner: TDOMDocument);
 | |
|     procedure AddToChildNodeTree(NewNode: TDOMNode);
 | |
|     procedure RemoveFromChildNodeTree(OldNode: TDOMNode);
 | |
|   public
 | |
|     destructor Destroy; override;
 | |
|     function InsertBefore(NewChild, RefChild: TDOMNode): TDOMNode; override;
 | |
|     function ReplaceChild(NewChild, OldChild: TDOMNode): TDOMNode; override;
 | |
|     function RemoveChild(OldChild: TDOMNode): TDOMNode; override;
 | |
|     function AppendChild(NewChild: TDOMNode): TDOMNode; override;
 | |
|     function HasChildNodes: Boolean; override;
 | |
|     function FindNode(const ANodeName: DOMString): TDOMNode; override;
 | |
|   end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   NodeList
 | |
| // -------------------------------------------------------
 | |
| 
 | |
|   TDOMNodeList = class(TRefClass)
 | |
|   protected
 | |
|     node: TDOMNode;
 | |
|     filter: DOMString;
 | |
|     UseFilter: Boolean;
 | |
|     function GetCount: LongInt;
 | |
|     function GetItem(index: LongWord): TDOMNode;
 | |
|   public
 | |
|     constructor Create(ANode: TDOMNode; const AFilter: DOMString);
 | |
|     property Item[index: LongWord]: TDOMNode read GetItem;
 | |
|     property Count: LongInt read GetCount;
 | |
|   end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   NamedNodeMap
 | |
| // -------------------------------------------------------
 | |
| 
 | |
|   TDOMNamedNodeMap = class(TFPList)
 | |
|   protected
 | |
|     OwnerDocument: TDOMDocument;
 | |
|     function GetItem(index: LongWord): TDOMNode;
 | |
|     procedure SetItem(index: LongWord; AItem: TDOMNode);
 | |
|     function GetLength: LongInt;
 | |
|   public
 | |
|     constructor Create(AOwner: TDOMDocument);
 | |
| 
 | |
|     function GetNamedItem(const name: DOMString): TDOMNode;
 | |
|     function SetNamedItem(arg: TDOMNode): TDOMNode;
 | |
|     function RemoveNamedItem(const name: DOMString): TDOMNode;
 | |
|     property Item[index: LongWord]: TDOMNode read GetItem write SetItem; default;
 | |
|     property Length: LongInt read GetLength;
 | |
|   end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   CharacterData
 | |
| // -------------------------------------------------------
 | |
| 
 | |
|   TDOMCharacterData = class(TDOMNode)
 | |
|   protected
 | |
|     function  GetLength: LongInt;
 | |
|   public
 | |
|     property Data: DOMString read FNodeValue;
 | |
|     property Length: LongInt read GetLength;
 | |
|     function SubstringData(offset, count: LongWord): DOMString;
 | |
|     procedure AppendData(const arg: DOMString);
 | |
|     procedure InsertData(offset: LongWord; const arg: DOMString);
 | |
|     procedure DeleteData(offset, count: LongWord);
 | |
|     procedure ReplaceData(offset, count: LongWord; const arg: DOMString);
 | |
|   end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   DOMImplementation
 | |
| // -------------------------------------------------------
 | |
| 
 | |
|   TDOMImplementation = class
 | |
|   public
 | |
|     function HasFeature(const feature, version: DOMString): Boolean;
 | |
| 
 | |
|     // Introduced in DOM Level 2:
 | |
| 
 | |
|     function CreateDocumentType(const QualifiedName, PublicID,
 | |
|       SystemID: DOMString): TDOMDocumentType;
 | |
|     function CreateDocument(const NamespaceURI, QualifiedName: DOMString;
 | |
|       doctype: TDOMDocumentType): TDOMDocument;
 | |
|   end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   DocumentFragment
 | |
| // -------------------------------------------------------
 | |
| 
 | |
|   TDOMDocumentFragment = class(TDOMNode_WithChildren)
 | |
|   public
 | |
|     constructor Create(AOwner: TDOMDocument);
 | |
|   end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   Document
 | |
| // -------------------------------------------------------
 | |
| 
 | |
|   TDOMDocument = class(TDOMNode_WithChildren)
 | |
|   protected
 | |
|     FDocType: TDOMDocumentType;
 | |
|     FImplementation: TDOMImplementation;
 | |
|     function GetDocumentElement: TDOMElement;
 | |
|   public
 | |
|     property DocType: TDOMDocumentType read FDocType;
 | |
|     property Impl: TDOMImplementation read FImplementation;
 | |
|     property DocumentElement: TDOMElement read GetDocumentElement;
 | |
| 
 | |
|     function CreateElement(const tagName: DOMString): TDOMElement; virtual;
 | |
|     function CreateDocumentFragment: TDOMDocumentFragment;
 | |
|     function CreateTextNode(const data: DOMString): TDOMText;
 | |
|     function CreateComment(const data: DOMString): TDOMComment;
 | |
|     function CreateCDATASection(const data: DOMString): TDOMCDATASection;
 | |
|       virtual;
 | |
|     function CreateProcessingInstruction(const target, data: DOMString):
 | |
|       TDOMProcessingInstruction; virtual;
 | |
|     function CreateAttribute(const name: DOMString): TDOMAttr; virtual;
 | |
|     function CreateEntityReference(const name: DOMString): TDOMEntityReference;
 | |
|       virtual;
 | |
|     // Free NodeList with TDOMNodeList.Release!
 | |
|     function GetElementsByTagName(const tagname: DOMString): TDOMNodeList;
 | |
| 
 | |
|     // Extensions to DOM interface:
 | |
|     constructor Create;
 | |
|     function CreateEntity(const data: DOMString): TDOMEntity;
 | |
|   end;
 | |
| 
 | |
|   TXMLDocument = class(TDOMDocument)
 | |
|   public
 | |
|     // These fields are extensions to the DOM interface:
 | |
|     XMLVersion, Encoding, StylesheetType, StylesheetHRef: DOMString;
 | |
| 
 | |
|     function CreateCDATASection(const data: DOMString): TDOMCDATASection; override;
 | |
|     function CreateProcessingInstruction(const target, data: DOMString):
 | |
|       TDOMProcessingInstruction; override;
 | |
|     function CreateEntityReference(const name: DOMString): TDOMEntityReference; override;
 | |
|   end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   Attr
 | |
| // -------------------------------------------------------
 | |
| 
 | |
|   TDOMAttr = class(TDOMNode_WithChildren)
 | |
|   protected
 | |
|     FSpecified: Boolean;
 | |
|     AttrOwner: TDOMNamedNodeMap;
 | |
|     function  GetNodeValue: DOMString; override;
 | |
|     procedure SetNodeValue(const AValue: DOMString); override;
 | |
|   public
 | |
|     constructor Create(AOwner: TDOMDocument);
 | |
| 
 | |
|     function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
 | |
|     property Name: DOMString read FNodeName;
 | |
|     property Specified: Boolean read FSpecified;
 | |
|     property Value: DOMString read GetNodeValue write SetNodeValue;
 | |
|   end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   Element
 | |
| // -------------------------------------------------------
 | |
| 
 | |
|   { TDOMElement }
 | |
| 
 | |
|   TDOMElement = class(TDOMNode_WithChildren)
 | |
|   private
 | |
|     FAttributes: TDOMNamedNodeMap;
 | |
|   protected
 | |
|     function GetAttributes: TDOMNamedNodeMap; override;
 | |
|   public
 | |
|     constructor Create(AOwner: TDOMDocument);
 | |
|     destructor Destroy; override;
 | |
|     function  CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
 | |
|     property  TagName: DOMString read FNodeName;
 | |
|     function  GetAttribute(const name: DOMString): DOMString;
 | |
|     procedure SetAttribute(const name, value: DOMString);
 | |
|     procedure RemoveAttribute(const name: DOMString);
 | |
|     function  GetAttributeNode(const name: DOMString): TDOMAttr;
 | |
|     procedure SetAttributeNode(NewAttr: TDOMAttr);
 | |
|     function  RemoveAttributeNode(OldAttr: TDOMAttr): TDOMAttr;
 | |
|     // Free NodeList with TDOMNodeList.Release!
 | |
|     function  GetElementsByTagName(const name: DOMString): TDOMNodeList;
 | |
|     function  IsEmpty: Boolean; override;
 | |
|     procedure Normalize;
 | |
| 
 | |
|     property AttribStrings[const Name: DOMString]: DOMString
 | |
|       read GetAttribute write SetAttribute; default;
 | |
|   end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   Text
 | |
| // -------------------------------------------------------
 | |
| 
 | |
|   TDOMText = class(TDOMCharacterData)
 | |
|   public
 | |
|     constructor Create(AOwner: TDOMDocument);
 | |
|     function  CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
 | |
|     function SplitText(offset: LongWord): TDOMText;
 | |
|   end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   Comment
 | |
| // -------------------------------------------------------
 | |
| 
 | |
|   TDOMComment = class(TDOMCharacterData)
 | |
|   public
 | |
|     constructor Create(AOwner: TDOMDocument);
 | |
|     function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
 | |
|   end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   CDATASection
 | |
| // -------------------------------------------------------
 | |
| 
 | |
|   TDOMCDATASection = class(TDOMText)
 | |
|   public
 | |
|     constructor Create(AOwner: TDOMDocument);
 | |
|     function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
 | |
|   end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   DocumentType
 | |
| // -------------------------------------------------------
 | |
| 
 | |
|   TDOMDocumentType = class(TDOMNode)
 | |
|   protected
 | |
|     FEntities, FNotations: TDOMNamedNodeMap;
 | |
|   public
 | |
|     constructor Create(AOwner: TDOMDocument);
 | |
|     function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
 | |
|     property Name: DOMString read FNodeName;
 | |
|     property Entities: TDOMNamedNodeMap read FEntities;
 | |
|     property Notations: TDOMNamedNodeMap read FEntities;
 | |
|   end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   Notation
 | |
| // -------------------------------------------------------
 | |
| 
 | |
|   TDOMNotation = class(TDOMNode)
 | |
|   protected
 | |
|     FPublicID, FSystemID: DOMString;
 | |
|   public
 | |
|     constructor Create(AOwner: TDOMDocument);
 | |
|     function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
 | |
|     property PublicID: DOMString read FPublicID;
 | |
|     property SystemID: DOMString read FSystemID;
 | |
|   end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   Entity
 | |
| // -------------------------------------------------------
 | |
| 
 | |
|   TDOMEntity = class(TDOMNode_WithChildren)
 | |
|   protected
 | |
|     FPublicID, FSystemID, FNotationName: DOMString;
 | |
|   public
 | |
|     constructor Create(AOwner: TDOMDocument);
 | |
|     property PublicID: DOMString read FPublicID;
 | |
|     property SystemID: DOMString read FSystemID;
 | |
|     property NotationName: DOMString read FNotationName;
 | |
|   end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   EntityReference
 | |
| // -------------------------------------------------------
 | |
| 
 | |
|   TDOMEntityReference = class(TDOMNode_WithChildren)
 | |
|   public
 | |
|     constructor Create(AOwner: TDOMDocument);
 | |
|   end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   ProcessingInstruction
 | |
| // -------------------------------------------------------
 | |
| 
 | |
|   TDOMProcessingInstruction = class(TDOMNode)
 | |
|   public
 | |
|     constructor Create(AOwner: TDOMDocument);
 | |
|     property Target: DOMString read FNodeName;
 | |
|     property Data: DOMString read FNodeValue;
 | |
|   end;
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| // =======================================================
 | |
| // =======================================================
 | |
| 
 | |
| implementation
 | |
| 
 | |
| 
 | |
| constructor TRefClass.Create;
 | |
| begin
 | |
|   inherited Create;
 | |
|   RefCounter := 1;
 | |
| end;
 | |
| 
 | |
| function TRefClass.AddRef: LongInt;
 | |
| begin
 | |
|   Inc(RefCounter);
 | |
|   Result := RefCounter;
 | |
| end;
 | |
| 
 | |
| function TRefClass.Release: LongInt;
 | |
| begin
 | |
|   Dec(RefCounter);
 | |
|   Result := RefCounter;
 | |
|   if RefCounter <= 0 then Free;
 | |
| end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   DOM Exception
 | |
| // -------------------------------------------------------
 | |
| 
 | |
| constructor EDOMError.Create(ACode: Integer; const ASituation: String);
 | |
| begin
 | |
|   Code := ACode;
 | |
|   inherited Create(Self.ClassName + ' in ' + ASituation);
 | |
| end;
 | |
| 
 | |
| constructor EDOMIndexSize.Create(const ASituation: String);    // 1
 | |
| begin
 | |
|   inherited Create(INDEX_SIZE_ERR, ASituation);
 | |
| end;
 | |
| 
 | |
| constructor EDOMHierarchyRequest.Create(const ASituation: String);    // 3
 | |
| begin
 | |
|   inherited Create(HIERARCHY_REQUEST_ERR, ASituation);
 | |
| end;
 | |
| 
 | |
| constructor EDOMWrongDocument.Create(const ASituation: String);    // 4
 | |
| begin
 | |
|   inherited Create(WRONG_DOCUMENT_ERR, ASituation);
 | |
| end;
 | |
| 
 | |
| constructor EDOMNotFound.Create(const ASituation: String);    // 8
 | |
| begin
 | |
|   inherited Create(NOT_FOUND_ERR, ASituation);
 | |
| end;
 | |
| 
 | |
| constructor EDOMNotSupported.Create(const ASituation: String);    // 9
 | |
| begin
 | |
|   inherited Create(NOT_SUPPORTED_ERR, ASituation);
 | |
| end;
 | |
| 
 | |
| constructor EDOMInUseAttribute.Create(const ASituation: String);    // 10
 | |
| begin
 | |
|   inherited Create(INUSE_ATTRIBUTE_ERR, ASituation);
 | |
| end;
 | |
| 
 | |
| constructor EDOMInvalidState.Create(const ASituation: String);    // 11
 | |
| begin
 | |
|   inherited Create(INVALID_STATE_ERR, ASituation);
 | |
| end;
 | |
| 
 | |
| constructor EDOMSyntax.Create(const ASituation: String);    // 12
 | |
| begin
 | |
|   inherited Create(SYNTAX_ERR, ASituation);
 | |
| end;
 | |
| 
 | |
| constructor EDOMInvalidModification.Create(const ASituation: String);    // 13
 | |
| begin
 | |
|   inherited Create(INVALID_MODIFICATION_ERR, ASituation);
 | |
| end;
 | |
| 
 | |
| constructor EDOMNamespace.Create(const ASituation: String);    // 14
 | |
| begin
 | |
|   inherited Create(NAMESPACE_ERR, ASituation);
 | |
| end;
 | |
| 
 | |
| constructor EDOMInvalidAccess.Create(const ASituation: String);    // 15
 | |
| begin
 | |
|   inherited Create(INVALID_ACCESS_ERR, ASituation);
 | |
| end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   Node
 | |
| // -------------------------------------------------------
 | |
| 
 | |
| constructor TDOMNode.Create(AOwner: TDOMDocument);
 | |
| begin
 | |
|   FOwnerDocument := AOwner;
 | |
|   inherited Create;
 | |
| end;
 | |
| 
 | |
| function TDOMNode.GetNodeValue: DOMString;
 | |
| begin
 | |
|   Result := FNodeValue;
 | |
| end;
 | |
| 
 | |
| procedure TDOMNode.SetNodeValue(const AValue: DOMString);
 | |
| begin
 | |
|   FNodeValue := AValue;
 | |
| end;
 | |
| 
 | |
| function TDOMNode.GetChildNodes: TDOMNodeList;
 | |
| begin
 | |
|   Result := TDOMNodeList.Create(Self, '*');
 | |
| end;
 | |
| 
 | |
| function TDOMNode.GetFirstChild: TDOMNode;
 | |
| begin
 | |
|   Result := nil;
 | |
| end;
 | |
| 
 | |
| function TDOMNode.GetLastChild: TDOMNode;
 | |
| begin
 | |
|   Result := nil;
 | |
| end;
 | |
| 
 | |
| function TDOMNode.GetAttributes: TDOMNamedNodeMap;
 | |
| begin
 | |
|   Result := nil;
 | |
| end;
 | |
| 
 | |
| function TDOMNode.InsertBefore(NewChild, RefChild: TDOMNode): TDOMNode;
 | |
| begin
 | |
|   raise EDOMHierarchyRequest.Create('Node.InsertBefore');
 | |
|   if (NewChild=nil) and (RefChild=nil) then ;
 | |
|   Result:=nil;
 | |
| end;
 | |
| 
 | |
| function TDOMNode.ReplaceChild(NewChild, OldChild: TDOMNode): TDOMNode;
 | |
| begin
 | |
|   raise EDOMHierarchyRequest.Create('Node.ReplaceChild');
 | |
|   if (NewChild=nil) and (OldChild=nil) then ;
 | |
|   Result:=nil;
 | |
| end;
 | |
| 
 | |
| function TDOMNode.RemoveChild(OldChild: TDOMNode): TDOMNode;
 | |
| begin
 | |
|   raise EDOMHierarchyRequest.Create('Node.RemoveChild');
 | |
|   if (OldChild=nil) then ;
 | |
|   Result:=nil;
 | |
| end;
 | |
| 
 | |
| function TDOMNode.AppendChild(NewChild: TDOMNode): TDOMNode;
 | |
| begin
 | |
|   raise EDOMHierarchyRequest.Create('Node.AppendChild');
 | |
|   if (NewChild=nil) then ;
 | |
|   Result:=nil;
 | |
| end;
 | |
| 
 | |
| function TDOMNode.HasChildNodes: Boolean;
 | |
| begin
 | |
|   Result := False;
 | |
| end;
 | |
| 
 | |
| function TDOMNode.CloneNode(deep: Boolean): TDOMNode;
 | |
| begin
 | |
|   if deep then ;
 | |
|   Result:=CloneNode(deep, FOwnerDocument);
 | |
| end;
 | |
| 
 | |
| function TDOMNode.IsEmpty: Boolean;
 | |
| begin
 | |
|   Result:=true;
 | |
| end;
 | |
| 
 | |
| function TDOMNode.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
 | |
| begin
 | |
|   raise EDOMNotSupported.Create('CloneNode not implemented for ' + ClassName);
 | |
|   if (deep) and (ACloneOwner=nil) then ;
 | |
|   Result:=nil;
 | |
| end;
 | |
| 
 | |
| function TDOMNode.FindNode(const ANodeName: DOMString): TDOMNode;
 | |
| var
 | |
|   child: TDOMNode;
 | |
| begin
 | |
|   child := FirstChild;
 | |
|   while Assigned(child) do
 | |
|   begin
 | |
|     if child.NodeName = ANodeName then
 | |
|     begin
 | |
|       Result := child;
 | |
|       exit;
 | |
|     end;
 | |
|     child := child.NextSibling;
 | |
|   end;
 | |
|   Result := nil;
 | |
| end;
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| 
 | |
| function CompareDOMStrings(const s1, s2: DOMPChar; l1, l2: integer): integer;
 | |
| var i: integer;
 | |
| begin
 | |
|   Result:=l1-l2;
 | |
|   i:=0;
 | |
|   while (i<l1) and (Result=0) do begin
 | |
|     Result:=ord(s1[i])-ord(s2[i]);
 | |
|     inc(i);
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| function CompareDOMNodeWithDOMNode(Node1, Node2: Pointer): integer;
 | |
| begin
 | |
|   Result:=CompareDOMStrings(DOMPChar(Pointer(TDOMNode(Node1).NodeName)),
 | |
|                             DOMPChar(Pointer(TDOMNode(Node2).NodeName)),
 | |
|                             length(TDOMNode(Node1).NodeName),
 | |
|                             length(TDOMNode(Node2).NodeName)
 | |
|                             );
 | |
| end;
 | |
| 
 | |
| function CompareDOMStringWithDOMNode(AKey, ANode: Pointer): integer;
 | |
| begin
 | |
|   Result:=CompareDOMStrings(DOMPChar(AKey),
 | |
|                             DOMPChar(Pointer(TDOMNode(ANode).NodeName)),
 | |
|                             length(DOMString(AKey)),
 | |
|                             length(TDOMNode(ANode).NodeName)
 | |
|                             );
 | |
| end;
 | |
| 
 | |
| 
 | |
| function TDOMNode_WithChildren.GetFirstChild: TDOMNode;
 | |
| begin
 | |
|   Result := FFirstChild;
 | |
| end;
 | |
| 
 | |
| function TDOMNode_WithChildren.GetLastChild: TDOMNode;
 | |
| begin
 | |
|   Result := FLastChild;
 | |
| end;
 | |
| 
 | |
| destructor TDOMNode_WithChildren.Destroy;
 | |
| var
 | |
|   child, next: TDOMNode;
 | |
| begin
 | |
|   if FChildNodeTree<>nil then begin
 | |
|     FChildNodeTree.Free;
 | |
|     FChildNodeTree:=nil;
 | |
|   end;
 | |
|   child := FirstChild;
 | |
|   while Assigned(child) do
 | |
|   begin
 | |
|     next := child.NextSibling;
 | |
|     child.Free;
 | |
|     child := next;
 | |
|   end;
 | |
|   inherited Destroy;
 | |
| end;
 | |
| 
 | |
| function TDOMNode_WithChildren.InsertBefore(NewChild, RefChild: TDOMNode):
 | |
|   TDOMNode;
 | |
| begin
 | |
|   Result := NewChild;
 | |
| 
 | |
|   if not Assigned(RefChild) then
 | |
|   begin
 | |
|     AppendChild(NewChild);
 | |
|     exit;
 | |
|   end;
 | |
| 
 | |
|   if NewChild.FOwnerDocument <> FOwnerDocument then
 | |
|     raise EDOMWrongDocument.Create('NodeWC.InsertBefore');
 | |
| 
 | |
|   if RefChild.ParentNode <> Self then
 | |
|     raise EDOMHierarchyRequest.Create('NodeWC.InsertBefore');
 | |
| 
 | |
|   if NewChild.NodeType = DOCUMENT_FRAGMENT_NODE then
 | |
|     raise EDOMNotSupported.Create('NodeWC.InsertBefore for DocumentFragment');
 | |
| 
 | |
|   NewChild.FNextSibling := RefChild;
 | |
|   if RefChild = FFirstChild then
 | |
|     FFirstChild := NewChild
 | |
|   else
 | |
|   begin
 | |
|     RefChild.FPreviousSibling.FNextSibling := NewChild;
 | |
|     NewChild.FPreviousSibling := RefChild.FPreviousSibling;
 | |
|   end;
 | |
| 
 | |
|   RefChild.FPreviousSibling := NewChild;
 | |
|   NewChild.FParentNode := Self;
 | |
|   AddToChildNodeTree(NewChild);
 | |
| end;
 | |
| 
 | |
| function TDOMNode_WithChildren.ReplaceChild(NewChild, OldChild: TDOMNode):
 | |
|   TDOMNode;
 | |
| begin
 | |
|   RemoveFromChildNodeTree(OldChild);
 | |
|   InsertBefore(NewChild, OldChild);
 | |
|   if Assigned(OldChild) then
 | |
|     RemoveChild(OldChild);
 | |
|   Result := NewChild;
 | |
| end;
 | |
| 
 | |
| function TDOMNode_WithChildren.RemoveChild(OldChild: TDOMNode):
 | |
|   TDOMNode;
 | |
| begin
 | |
|   if OldChild.ParentNode <> Self then
 | |
|     raise EDOMHierarchyRequest.Create('NodeWC.RemoveChild');
 | |
| 
 | |
|   if OldChild = FFirstChild then
 | |
|     FFirstChild := FFirstChild.NextSibling
 | |
|   else
 | |
|     OldChild.FPreviousSibling.FNextSibling := OldChild.FNextSibling;
 | |
| 
 | |
|   if OldChild = FLastChild then
 | |
|     FLastChild := FLastChild.FPreviousSibling
 | |
|   else
 | |
|     OldChild.FNextSibling.FPreviousSibling := OldChild.FPreviousSibling;
 | |
| 
 | |
|   RemoveFromChildNodeTree(OldChild);
 | |
|   OldChild.Free;
 | |
|   Result:=nil;
 | |
| end;
 | |
| 
 | |
| function TDOMNode_WithChildren.AppendChild(NewChild: TDOMNode): TDOMNode;
 | |
| var
 | |
|   Parent: TDOMNode;
 | |
| begin
 | |
|   //writeln('TDOMNode_WithChildren.AppendChild ',NodeName,' NewChild=',NewChild.NodeName);
 | |
|   if NewChild.FOwnerDocument <> FOwnerDocument then
 | |
|     raise EDOMWrongDocument.Create('NodeWC.AppendChild');
 | |
| 
 | |
|   Parent := Self;
 | |
|   while Assigned(Parent) do
 | |
|   begin
 | |
|     if Parent = NewChild then
 | |
|       raise EDOMHierarchyRequest.Create('NodeWC.AppendChild (cycle in tree)');
 | |
|     Parent := Parent.ParentNode;
 | |
|   end;
 | |
| 
 | |
|   if NewChild.FParentNode<>nil then begin
 | |
|     //writeln('TDOMNode_WithChildren.AppendChild old NewChild.FParentNode=',NewChild.FParentNode.NodeName);
 | |
|     NewChild.FParentNode.RemoveChild(NewChild);
 | |
|   end;
 | |
| 
 | |
|   if NewChild.NodeType = DOCUMENT_FRAGMENT_NODE then
 | |
|     raise EDOMNotSupported.Create('NodeWC.AppendChild for DocumentFragments')
 | |
|   else begin
 | |
|     if Assigned(FFirstChild) then
 | |
|     begin
 | |
|       FLastChild.FNextSibling := NewChild;
 | |
|       NewChild.FPreviousSibling := FLastChild;
 | |
|     end else
 | |
|       FFirstChild := NewChild;
 | |
|     FLastChild := NewChild;
 | |
|     NewChild.FParentNode := Self;
 | |
|   end;
 | |
|   AddToChildNodeTree(NewChild);
 | |
|   Result := NewChild;
 | |
| end;
 | |
| 
 | |
| function TDOMNode_WithChildren.HasChildNodes: Boolean;
 | |
| begin
 | |
|   Result := Assigned(FFirstChild);
 | |
| end;
 | |
| 
 | |
| function TDOMNode_WithChildren.FindNode(const ANodeName: DOMString): TDOMNode;
 | |
| var
 | |
|   AVLNode: TAVLTreeNode;
 | |
| begin
 | |
|   Result:=nil;
 | |
|   if FChildNodeTree<>nil then begin
 | |
|     // use tree for fast search
 | |
|     //if FChildNodeTree.ConsistencyCheck<>0 then
 | |
|     //  raise exception.Create('TDOMNode_WithChildren.FindNode');
 | |
|     AVLNode:=FChildNodeTree.FindKey(DOMPChar(Pointer(ANodeName)),
 | |
|                                     @CompareDOMStringWithDOMNode);
 | |
|     if AVLNode<>nil then
 | |
|       Result:=TDOMNode(AVLNode.Data);
 | |
|   end else begin
 | |
|     // search in list
 | |
|     Result := FirstChild;
 | |
|     while Assigned(Result) do begin
 | |
|       if CompareDOMStringWithDOMNode(DOMPChar(Pointer(ANodeName)),Result)=0
 | |
|       then exit;
 | |
|       Result := Result.NextSibling;
 | |
|     end;
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| procedure TDOMNode_WithChildren.CloneChildren(ACopy: TDOMNode;
 | |
|   ACloneOwner: TDOMDocument);
 | |
| var
 | |
|   node: TDOMNode;
 | |
| begin
 | |
|   node := FirstChild;
 | |
|   while Assigned(node) do
 | |
|   begin
 | |
|     ACopy.AppendChild(node.CloneNode(True, ACloneOwner));
 | |
|     node := node.NextSibling;
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| procedure TDOMNode_WithChildren.AddToChildNodeTree(NewNode: TDOMNode);
 | |
| var
 | |
|   ChildCount: Integer;
 | |
|   ANode: TDOMNode;
 | |
|   NewNodeAdded: Boolean;
 | |
| begin
 | |
|   if (FChildNodeTree=nil) then begin
 | |
|     // there is no childnodetree yet
 | |
|     // Most xml trees contains nodes with only a few child nodes. It would be
 | |
|     // overhead to create a tree for only a few childs.
 | |
|     ChildCount := 0;
 | |
|     ANode := FirstChild;
 | |
|     while Assigned(ANode) do begin
 | |
|       inc(ChildCount);
 | |
|       ANode := ANode.NextSibling;
 | |
|     end;
 | |
|     if ChildCount>5 then begin
 | |
|       FChildNodeTree:=TAVLTree.Create(@CompareDOMNodeWithDOMNode);
 | |
|       // add all existing childs
 | |
|       ANode := FirstChild;
 | |
|       NewNodeAdded:=false;
 | |
|       while Assigned(ANode) do begin
 | |
|         if ANode=NewNode then NewNodeAdded:=true;
 | |
|         FChildNodeTree.Add(ANode);
 | |
|         ANode := ANode.NextSibling;
 | |
|       end;
 | |
|       if not NewNodeAdded then
 | |
|         FChildNodeTree.Add(NewNode);
 | |
|     end;
 | |
|   end else begin
 | |
|     {if (FChildNodeTree.Find(NewNode)<>nil) then begin
 | |
|       writeln('TDOMNode_WithChildren.AddToChildNodeTree adding same value ',NewNOde.NodeName);
 | |
|       CTDumpStack;
 | |
|     end;}
 | |
|     FChildNodeTree.Add(NewNode);
 | |
|   end;
 | |
|   //if FChildNodeTree.ConsistencyCheck<>0 then
 | |
|   //  raise exception.Create('TDOMNode_WithChildren.FindNode');
 | |
| end;
 | |
| 
 | |
| procedure TDOMNode_WithChildren.RemoveFromChildNodeTree(OldNode: TDOMNode);
 | |
| begin
 | |
|   if FChildNodeTree<>nil then
 | |
|     FChildNodeTree.RemovePointer(OldNode);// doubles are allowed, so Remove can not be used
 | |
|   //if (FChildNodeTree<>nil) and (FChildNodeTree.ConsistencyCheck<>0) then
 | |
|   //  raise exception.Create('TDOMNode_WithChildren.FindNode');
 | |
| end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   NodeList
 | |
| // -------------------------------------------------------
 | |
| 
 | |
| constructor TDOMNodeList.Create(ANode: TDOMNode; const AFilter: DOMString);
 | |
| begin
 | |
|   inherited Create;
 | |
|   node := ANode;
 | |
|   filter := AFilter;
 | |
|   UseFilter := filter <> '*';
 | |
| end;
 | |
| 
 | |
| function TDOMNodeList.GetCount: LongInt;
 | |
| var
 | |
|   child: TDOMNode;
 | |
| begin
 | |
|   Result := 0;
 | |
|   child := node.FirstChild;
 | |
|   while Assigned(child) do
 | |
|   begin
 | |
|     if (not UseFilter) or (child.NodeName = filter) then
 | |
|       Inc(Result);
 | |
|     child := child.NextSibling;
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| function TDOMNodeList.GetItem(index: LongWord): TDOMNode;
 | |
| var
 | |
|   child: TDOMNode;
 | |
| begin
 | |
|   Result := nil;
 | |
|   child := node.FirstChild;
 | |
|   while Assigned(child) do
 | |
|   begin
 | |
|     if index = 0 then
 | |
|     begin
 | |
|       Result := child;
 | |
|       break;
 | |
|     end;
 | |
|     if (not UseFilter) or (child.NodeName = filter) then
 | |
|       Dec(index);
 | |
|     child := child.NextSibling;
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   NamedNodeMap
 | |
| // -------------------------------------------------------
 | |
| 
 | |
| constructor TDOMNamedNodeMap.Create(AOwner: TDOMDocument);
 | |
| begin
 | |
|   inherited Create;
 | |
|   OwnerDocument := AOwner;
 | |
| end;
 | |
| 
 | |
| function TDOMNamedNodeMap.GetItem(index: LongWord): TDOMNode;
 | |
| begin
 | |
|   Result := TDOMNode(Items[index]);
 | |
| end;
 | |
| 
 | |
| procedure TDOMNamedNodeMap.SetItem(index: LongWord; AItem: TDOMNode);
 | |
| begin
 | |
|   Items[index] := AItem;
 | |
| end;
 | |
| 
 | |
| function TDOMNamedNodeMap.GetLength: LongInt;
 | |
| begin
 | |
|   Result := Count;
 | |
| end;
 | |
| 
 | |
| function TDOMNamedNodeMap.GetNamedItem(const name: DOMString): TDOMNode;
 | |
| var
 | |
|   i: Integer;
 | |
| begin
 | |
|   for i := 0 to Count - 1 do
 | |
|   begin
 | |
|     Result := Item[i];
 | |
|     if Result.NodeName = name then
 | |
|       exit;
 | |
|   end;
 | |
|   Result := nil;
 | |
| end;
 | |
| 
 | |
| function TDOMNamedNodeMap.SetNamedItem(arg: TDOMNode): TDOMNode;
 | |
| var
 | |
|   i: Integer;
 | |
| begin
 | |
|   if arg.FOwnerDocument <> OwnerDocument then
 | |
|     raise EDOMWrongDocument.Create('NamedNodeMap.SetNamedItem');
 | |
| 
 | |
|   if arg.NodeType = ATTRIBUTE_NODE then
 | |
|   begin
 | |
|     if Assigned(TDOMAttr(arg).AttrOwner) then
 | |
|       raise EDOMInUseAttribute.Create('NamedNodeMap.SetNamedItem');
 | |
|     TDOMAttr(arg).AttrOwner := Self;
 | |
|   end;
 | |
| 
 | |
|   for i := 0 to Count - 1 do
 | |
|     if Item[i].NodeName = arg.NodeName then
 | |
|     begin
 | |
|       Result := Item[i];
 | |
|       Item[i] := arg;
 | |
|       exit;
 | |
|     end;
 | |
|   Add(arg);
 | |
|   Result := nil;
 | |
| end;
 | |
| 
 | |
| function TDOMNamedNodeMap.RemoveNamedItem(const name: DOMString): TDOMNode;
 | |
| var
 | |
|   i: Integer;
 | |
| begin
 | |
|   for i := 0 to Count - 1 do
 | |
|     if Item[i].NodeName = name then
 | |
|     begin
 | |
|       Result := Item[i];
 | |
|       Result.FParentNode := nil;
 | |
|       exit;
 | |
|     end;
 | |
|   raise EDOMNotFound.Create('NamedNodeMap.RemoveNamedItem');
 | |
| end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   CharacterData
 | |
| // -------------------------------------------------------
 | |
| 
 | |
| function TDOMCharacterData.GetLength: LongInt;
 | |
| begin
 | |
|   Result := system.Length(FNodeValue);
 | |
| end;
 | |
| 
 | |
| function TDOMCharacterData.SubstringData(offset, count: LongWord): DOMString;
 | |
| begin
 | |
|   if (offset < 0) or (longint(offset) > Length) or (count < 0) then
 | |
|     raise EDOMIndexSize.Create('CharacterData.SubstringData');
 | |
|   Result := Copy(FNodeValue, offset + 1, count);
 | |
| end;
 | |
| 
 | |
| procedure TDOMCharacterData.AppendData(const arg: DOMString);
 | |
| begin
 | |
|   FNodeValue := FNodeValue + arg;
 | |
| end;
 | |
| 
 | |
| procedure TDOMCharacterData.InsertData(offset: LongWord; const arg: DOMString);
 | |
| begin
 | |
|   if (offset < 0) or (longint(offset) > Length) then
 | |
|     raise EDOMIndexSize.Create('CharacterData.InsertData');
 | |
| 
 | |
|   FNodeValue := Copy(FNodeValue, 1, offset) + arg +
 | |
|     Copy(FNodeValue, offset + 1, Length);
 | |
| end;
 | |
| 
 | |
| procedure TDOMCharacterData.DeleteData(offset, count: LongWord);
 | |
| begin
 | |
|   if (offset < 0) or (longint(offset) > Length) or (count < 0) then
 | |
|     raise EDOMIndexSize.Create('CharacterData.DeleteData');
 | |
| 
 | |
|   FNodeValue := Copy(FNodeValue, 1, offset) +
 | |
|     Copy(FNodeValue, offset + count + 1, Length);
 | |
| end;
 | |
| 
 | |
| procedure TDOMCharacterData.ReplaceData(offset, count: LongWord; const arg: DOMString);
 | |
| begin
 | |
|   DeleteData(offset, count);
 | |
|   InsertData(offset, arg);
 | |
| end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   DocumentFragmet
 | |
| // -------------------------------------------------------
 | |
| 
 | |
| constructor TDOMDocumentFragment.Create(AOwner: TDOMDocument);
 | |
| begin
 | |
|   FNodeType := DOCUMENT_FRAGMENT_NODE;
 | |
|   FNodeName := '#document-fragment';
 | |
|   inherited Create(AOwner);
 | |
| end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   DOMImplementation
 | |
| // -------------------------------------------------------
 | |
| 
 | |
| function TDOMImplementation.HasFeature(const feature, version: DOMString):
 | |
|   Boolean;
 | |
| begin
 | |
|   Result := False;
 | |
|   if (feature='') and (version='') then ;
 | |
| end;
 | |
| 
 | |
| function TDOMImplementation.CreateDocumentType(const QualifiedName, PublicID,
 | |
|   SystemID: DOMString): TDOMDocumentType;
 | |
| begin
 | |
|   // !!!: Implement this method (easy to do)
 | |
|   raise EDOMNotSupported.Create('DOMImplementation.CreateDocumentType');
 | |
|   if (QualifiedName='') and (PublicID='') and (SystemID='') then ;
 | |
|   Result:=nil;
 | |
| end;
 | |
| 
 | |
| function TDOMImplementation.CreateDocument(const NamespaceURI,
 | |
|   QualifiedName: DOMString; doctype: TDOMDocumentType): TDOMDocument;
 | |
| begin
 | |
|   // !!!: Implement this method (easy to do)
 | |
|   raise EDOMNotSupported.Create('DOMImplementation.CreateDocument');
 | |
|   if (NamespaceURI='') and (QualifiedName='') and (doctype=nil) then ;
 | |
|   Result:=nil;
 | |
| end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   Document
 | |
| // -------------------------------------------------------
 | |
| 
 | |
| constructor TDOMDocument.Create;
 | |
| begin
 | |
|   FNodeType := DOCUMENT_NODE;
 | |
|   FNodeName := '#document';
 | |
|   inherited Create(nil);
 | |
|   FOwnerDocument := Self;
 | |
| end;
 | |
| 
 | |
| function TDOMDocument.GetDocumentElement: TDOMElement;
 | |
| var
 | |
|   node: TDOMNode;
 | |
| begin
 | |
|   node := FFirstChild;
 | |
|   while Assigned(node) do
 | |
|   begin
 | |
|     if node.FNodeType = ELEMENT_NODE then
 | |
|     begin
 | |
|       Result := TDOMElement(node);
 | |
|       exit;
 | |
|     end;
 | |
|     node := node.NextSibling;
 | |
|   end;
 | |
|   Result := nil;
 | |
| end;
 | |
| 
 | |
| function TDOMDocument.CreateElement(const tagName: DOMString): TDOMElement;
 | |
| begin
 | |
|   Result := TDOMElement.Create(Self);
 | |
|   Result.FNodeName := tagName;
 | |
| end;
 | |
| 
 | |
| function TDOMDocument.CreateDocumentFragment: TDOMDocumentFragment;
 | |
| begin
 | |
|   Result := TDOMDocumentFragment.Create(Self);
 | |
| end;
 | |
| 
 | |
| function TDOMDocument.CreateTextNode(const data: DOMString): TDOMText;
 | |
| begin
 | |
|   Result := TDOMText.Create(Self);
 | |
|   Result.FNodeValue := data;
 | |
| end;
 | |
| 
 | |
| function TDOMDocument.CreateComment(const data: DOMString): TDOMComment;
 | |
| begin
 | |
|   Result := TDOMComment.Create(Self);
 | |
|   Result.FNodeValue := data;
 | |
| end;
 | |
| 
 | |
| function TDOMDocument.CreateCDATASection(const data: DOMString):
 | |
|   TDOMCDATASection;
 | |
| begin
 | |
|   raise EDOMNotSupported.Create('DOMDocument.CreateCDATASection');
 | |
|   if data='' then ;
 | |
|   Result:=nil;
 | |
| end;
 | |
| 
 | |
| function TDOMDocument.CreateProcessingInstruction(const target,
 | |
|   data: DOMString): TDOMProcessingInstruction;
 | |
| begin
 | |
|   raise EDOMNotSupported.Create('DOMDocument.CreateProcessingInstruction');
 | |
|   if (target='') and (data='') then ;
 | |
|   Result:=nil;
 | |
| end;
 | |
| 
 | |
| function TDOMDocument.CreateAttribute(const name: DOMString): TDOMAttr;
 | |
| begin
 | |
|   Result := TDOMAttr.Create(Self);
 | |
|   Result.FNodeName := name;
 | |
| end;
 | |
| 
 | |
| function TDOMDocument.CreateEntityReference(const name: DOMString):
 | |
|   TDOMEntityReference;
 | |
| begin
 | |
|   raise EDOMNotSupported.Create('DOMDocument.CreateEntityReference');
 | |
|   if name='' then ;
 | |
|   Result:=nil;
 | |
| end;
 | |
| 
 | |
| function TDOMDocument.CreateEntity(const data: DOMString): TDOMEntity;
 | |
| begin
 | |
|   Result := TDOMEntity.Create(Self);
 | |
|   Result.FNodeName := data;
 | |
| end;
 | |
| 
 | |
| function TDOMDocument.GetElementsByTagName(const tagname: DOMString): TDOMNodeList;
 | |
| begin
 | |
|   Result := TDOMNodeList.Create(Self, tagname);
 | |
| end;
 | |
| 
 | |
| 
 | |
| function TXMLDocument.CreateCDATASection(const data: DOMString):
 | |
|   TDOMCDATASection;
 | |
| begin
 | |
|   Result := TDOMCDATASection.Create(Self);
 | |
|   Result.FNodeValue := data;
 | |
| end;
 | |
| 
 | |
| function TXMLDocument.CreateProcessingInstruction(const target,
 | |
|   data: DOMString): TDOMProcessingInstruction;
 | |
| begin
 | |
|   Result := TDOMProcessingInstruction.Create(Self);
 | |
|   Result.FNodeName := target;
 | |
|   Result.FNodeValue := data;
 | |
| end;
 | |
| 
 | |
| function TXMLDocument.CreateEntityReference(const name: DOMString):
 | |
|   TDOMEntityReference;
 | |
| begin
 | |
|   Result := TDOMEntityReference.Create(Self);
 | |
|   Result.FNodeName := name;
 | |
| end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   Attr
 | |
| // -------------------------------------------------------
 | |
| 
 | |
| constructor TDOMAttr.Create(AOwner: TDOMDocument);
 | |
| begin
 | |
|   FNodeType := ATTRIBUTE_NODE;
 | |
|   inherited Create(AOwner);
 | |
| end;
 | |
| 
 | |
| function TDOMAttr.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
 | |
| begin
 | |
|   Result := TDOMAttr.Create(ACloneOwner);
 | |
|   Result.FNodeName := FNodeName;
 | |
|   TDOMAttr(Result).FSpecified := FSpecified;
 | |
|   if deep then
 | |
|     CloneChildren(Result, ACloneOwner);
 | |
| end;
 | |
| 
 | |
| function TDOMAttr.GetNodeValue: DOMString;
 | |
| var
 | |
|   child: TDOMNode;
 | |
| begin
 | |
|   SetLength(Result, 0);
 | |
|   if Assigned(FFirstChild) then
 | |
|   begin
 | |
|     child := FFirstChild;
 | |
|     while Assigned(child) do
 | |
|     begin
 | |
|       if child.NodeType = ENTITY_REFERENCE_NODE then
 | |
|         Result := Result + '&' + child.NodeName + ';'
 | |
|       else
 | |
|         Result := Result + child.NodeValue;
 | |
|       child := child.NextSibling;
 | |
|     end;
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| procedure TDOMAttr.SetNodeValue(const AValue: DOMString);
 | |
| var
 | |
|   tn: TDOMText;
 | |
| begin
 | |
|   FSpecified := True;
 | |
|   tn := TDOMText.Create(FOwnerDocument);
 | |
|   tn.FNodeValue := AValue;
 | |
|   if Assigned(FFirstChild) then
 | |
|     ReplaceChild(tn, FFirstChild)
 | |
|   else
 | |
|     AppendChild(tn);
 | |
| end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   Element
 | |
| // -------------------------------------------------------
 | |
| 
 | |
| constructor TDOMElement.Create(AOwner: TDOMDocument);
 | |
| begin
 | |
|   FNodeType := ELEMENT_NODE;
 | |
|   inherited Create(AOwner);
 | |
| end;
 | |
| 
 | |
| destructor TDOMElement.Destroy;
 | |
| var
 | |
|   i: Integer;
 | |
| begin
 | |
|   {As the attributes are _not_ childs of the element node, we have to free
 | |
|    them manually here:}
 | |
|   if FAttributes<>nil then begin
 | |
|     for i := 0 to FAttributes.Count - 1 do
 | |
|       FAttributes[i].Free;
 | |
|     FAttributes.Free;
 | |
|     FAttributes:=nil;
 | |
|   end;
 | |
|   inherited Destroy;
 | |
| end;
 | |
| 
 | |
| function TDOMElement.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
 | |
| var
 | |
|   i: Integer;
 | |
| begin
 | |
|   Result := TDOMElement.Create(ACloneOwner);
 | |
|   Result.FNodeName := FNodeName;
 | |
|   if FAttributes<>nil then begin
 | |
|     TDOMElement(Result).GetAttributes;
 | |
|     for i := 0 to FAttributes.Count - 1 do
 | |
|       TDOMElement(Result).FAttributes.Add(FAttributes[i].CloneNode(True, ACloneOwner));
 | |
|   end;
 | |
|   if deep then
 | |
|     CloneChildren(Result, ACloneOwner);
 | |
| end;
 | |
| 
 | |
| function TDOMElement.GetAttributes: TDOMNamedNodeMap;
 | |
| begin
 | |
|   if FAttributes=nil then
 | |
|     FAttributes := TDOMNamedNodeMap.Create(FOwnerDocument);
 | |
|   Result := FAttributes;
 | |
| end;
 | |
| 
 | |
| function TDOMElement.GetAttribute(const name: DOMString): DOMString;
 | |
| var
 | |
|   i: Integer;
 | |
| begin
 | |
|   if FAttributes<>nil then begin
 | |
|     for i := 0 to FAttributes.Count - 1 do
 | |
|       if FAttributes[i].NodeName = name then
 | |
|       begin
 | |
|         Result := FAttributes[i].NodeValue;
 | |
|         exit;
 | |
|       end;
 | |
|   end;
 | |
|   SetLength(Result, 0);
 | |
| end;
 | |
| 
 | |
| procedure TDOMElement.SetAttribute(const name, value: DOMString);
 | |
| var
 | |
|   i: Integer;
 | |
|   attr: TDOMAttr;
 | |
| begin
 | |
|   GetAttributes;
 | |
|   for i := 0 to FAttributes.Count - 1 do
 | |
|     if FAttributes[i].NodeName = name then
 | |
|     begin
 | |
|       FAttributes[i].NodeValue := value;
 | |
|       exit;
 | |
|     end;
 | |
|   attr := TDOMAttr.Create(FOwnerDocument);
 | |
|   attr.FNodeName := name;
 | |
|   attr.NodeValue := value;
 | |
|   FAttributes.Add(attr);
 | |
| end;
 | |
| 
 | |
| procedure TDOMElement.RemoveAttribute(const name: DOMString);
 | |
| var
 | |
|   i: Integer;
 | |
| begin
 | |
|   if FAttributes=nil then exit;
 | |
|   for i := 0 to FAttributes.Count - 1 do
 | |
|     if FAttributes[i].NodeName = name then
 | |
|     begin
 | |
|       FAttributes[i].Free;
 | |
|       FAttributes.Delete(i);
 | |
|       exit;
 | |
|     end;
 | |
| end;
 | |
| 
 | |
| function TDOMElement.GetAttributeNode(const name: DOMString): TDOMAttr;
 | |
| var
 | |
|   i: Integer;
 | |
| begin
 | |
|   if FAttributes<>nil then begin
 | |
|     for i := 0 to FAttributes.Count - 1 do
 | |
|       if FAttributes[i].NodeName = name then
 | |
|       begin
 | |
|         Result := TDOMAttr(FAttributes[i]);
 | |
|         exit;
 | |
|       end;
 | |
|   end;
 | |
|   Result := nil;
 | |
| end;
 | |
| 
 | |
| procedure TDOMElement.SetAttributeNode(NewAttr: TDOMAttr);
 | |
| var
 | |
|   i: Integer;
 | |
| begin
 | |
|   if FAttributes=nil then exit;
 | |
|   for i := 0 to FAttributes.Count - 1 do
 | |
|     if FAttributes[i].NodeName = NewAttr.NodeName then
 | |
|     begin
 | |
|       FAttributes[i].Free;
 | |
|       FAttributes[i] := NewAttr;
 | |
|       exit;
 | |
|     end;
 | |
| end;
 | |
| 
 | |
| function TDOMElement.RemoveAttributeNode(OldAttr: TDOMAttr): TDOMAttr;
 | |
| var
 | |
|   i: Integer;
 | |
|   node: TDOMNode;
 | |
| begin
 | |
|   Result:=nil;
 | |
|   if FAttributes=nil then exit;
 | |
|   for i := 0 to FAttributes.Count - 1 do
 | |
|   begin
 | |
|     node := FAttributes[i];
 | |
|     if node = OldAttr then
 | |
|     begin
 | |
|       FAttributes.Delete(i);
 | |
|       Result := TDOMAttr(node);
 | |
|       exit;
 | |
|     end;
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| function TDOMElement.GetElementsByTagName(const name: DOMString): TDOMNodeList;
 | |
| begin
 | |
|   Result := TDOMNodeList.Create(Self, name);
 | |
| end;
 | |
| 
 | |
| function TDOMElement.IsEmpty: Boolean;
 | |
| begin
 | |
|   Result:=(FAttributes=nil) or (FAttributes.Count=0)
 | |
| end;
 | |
| 
 | |
| procedure TDOMElement.Normalize;
 | |
| begin
 | |
|   // !!!: Not implemented
 | |
| end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   Text
 | |
| // -------------------------------------------------------
 | |
| 
 | |
| constructor TDOMText.Create(AOwner: TDOMDocument);
 | |
| begin
 | |
|   FNodeType := TEXT_NODE;
 | |
|   FNodeName := '#text';
 | |
|   inherited Create(AOwner);
 | |
| end;
 | |
| 
 | |
| function TDOMText.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
 | |
| begin
 | |
|   Result := TDOMText.Create(ACloneOwner);
 | |
|   Result.FNodeValue := FNodeValue;
 | |
|   if deep and (ACloneOwner=nil) then ;
 | |
| end;
 | |
| 
 | |
| function TDOMText.SplitText(offset: LongWord): TDOMText;
 | |
| begin
 | |
|   if longint(offset) > Length then
 | |
|     raise EDOMIndexSize.Create('Text.SplitText');
 | |
| 
 | |
|   Result := TDOMText.Create(FOwnerDocument);
 | |
|   Result.FNodeValue := Copy(FNodeValue, offset + 1, Length);
 | |
|   FNodeValue := Copy(FNodeValue, 1, offset);
 | |
|   FParentNode.InsertBefore(Result, FNextSibling);
 | |
| end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   Comment
 | |
| // -------------------------------------------------------
 | |
| 
 | |
| constructor TDOMComment.Create(AOwner: TDOMDocument);
 | |
| begin
 | |
|   FNodeType := COMMENT_NODE;
 | |
|   FNodeName := '#comment';
 | |
|   inherited Create(AOwner);
 | |
| end;
 | |
| 
 | |
| function TDOMComment.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
 | |
| begin
 | |
|   Result := TDOMComment.Create(ACloneOwner);
 | |
|   Result.FNodeValue := FNodeValue;
 | |
|   if deep and (ACloneOwner=nil) then ;
 | |
| end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   CDATASection
 | |
| // -------------------------------------------------------
 | |
| 
 | |
| constructor TDOMCDATASection.Create(AOwner: TDOMDocument);
 | |
| begin
 | |
|   inherited Create(AOwner);
 | |
|   FNodeType := CDATA_SECTION_NODE;
 | |
|   FNodeName := '#cdata-section';
 | |
| end;
 | |
| 
 | |
| function TDOMCDATASection.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
 | |
| begin
 | |
|   Result := TDOMCDATASection.Create(ACloneOwner);
 | |
|   Result.FNodeValue := FNodeValue;
 | |
|   if deep and (ACloneOwner=nil) then ;
 | |
| end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   DocumentType
 | |
| // -------------------------------------------------------
 | |
| 
 | |
| constructor TDOMDocumentType.Create(AOwner: TDOMDocument);
 | |
| begin
 | |
|   FNodeType := DOCUMENT_TYPE_NODE;
 | |
|   inherited Create(AOwner);
 | |
| end;
 | |
| 
 | |
| function TDOMDocumentType.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
 | |
| begin
 | |
|   Result := TDOMDocumentType.Create(ACloneOwner);
 | |
|   Result.FNodeName := FNodeName;
 | |
|   if deep and (ACloneOwner=nil) then ;
 | |
| end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   Notation
 | |
| // -------------------------------------------------------
 | |
| 
 | |
| constructor TDOMNotation.Create(AOwner: TDOMDocument);
 | |
| begin
 | |
|   FNodeType := NOTATION_NODE;
 | |
|   inherited Create(AOwner);
 | |
| end;
 | |
| 
 | |
| function TDOMNotation.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
 | |
| begin
 | |
|   Result := TDOMNotation.Create(ACloneOwner);
 | |
|   Result.FNodeName := FNodeName;
 | |
|   if deep and (ACloneOwner=nil) then ;
 | |
| end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   Entity
 | |
| // -------------------------------------------------------
 | |
| 
 | |
| constructor TDOMEntity.Create(AOwner: TDOMDocument);
 | |
| begin
 | |
|   FNodeType := ENTITY_NODE;
 | |
|   inherited Create(AOwner);
 | |
| end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   EntityReference
 | |
| // -------------------------------------------------------
 | |
| 
 | |
| constructor TDOMEntityReference.Create(AOwner: TDOMDocument);
 | |
| begin
 | |
|   FNodeType := ENTITY_REFERENCE_NODE;
 | |
|   inherited Create(AOwner);
 | |
| end;
 | |
| 
 | |
| 
 | |
| // -------------------------------------------------------
 | |
| //   ProcessingInstruction
 | |
| // -------------------------------------------------------
 | |
| 
 | |
| constructor TDOMProcessingInstruction.Create(AOwner: TDOMDocument);
 | |
| begin
 | |
|   FNodeType := PROCESSING_INSTRUCTION_NODE;
 | |
|   inherited Create(AOwner);
 | |
| end;
 | |
| 
 | |
| 
 | |
| end.
 | |
| 
 | |
| 
 | 
