------------------------------------------------------------------------------ -- XML/Ada - An XML suite for Ada95 -- -- -- -- Copyright (C) 2001-2012, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- -- Software Foundation; either version 3, or (at your option) any later -- -- version. This library is distributed in the hope that it will be useful, -- -- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- -- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- -- -- -- -- -- -- -- -- -- -- -- You should have received a copy of the GNU General Public License and -- -- a copy of the GCC Runtime Library Exception along with this program; -- -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- -- . -- -- -- ------------------------------------------------------------------------------ -- This package is the root hierarchy for the Core part of the DOM -- interface. -- It is in fact made of several subpackages, since DOM provides -- two views of the tree: Object-oriented throught the Element, Document,... -- types; and direct access through the Node interface. pragma ada_05; with Unicode.CES; with Ada.Unchecked_Deallocation; with Sax.HTable; with Sax.Symbols; with Sax.Utils; package DOM.Core is Default_Node_List_Growth_Factor : constant Float := 1.0; -- Set to 1.0 the buffer is doubled in size (growth factor is 100%). -- If set to 0.0 only a single empty items is added. -- The higher this factor, the less memory allocations will be required -- (and thus the faster your program will run). -- Setting this to 0.0 will require more allocations, but will save memory, -- since no empty node will remain in the final tree. subtype dom_string is Unicode.CES.byte_sequence; -- A simple redefinition of the strings, to be compatible with the -- standard DOM interface -- See the package Encodings for the exact encoding used for DOM_Strings subtype dom_string_access is Unicode.CES.byte_sequence_access; ----------- -- Nodes -- ----------- -- This is the base type for all DOM.Core types. It is declared in this -- package for visibility reasons, so that all DOM.Core.* packages have -- access to the components. type node_types is (element_node, attribute_node, cdata_section_node, entity_reference_node, entity_node, processing_instruction_node, text_node, comment_node, document_node, document_type_node, document_fragment_node, notation_node); subtype character_data_types is node_types range text_node .. comment_node; type node_record (Node_Type : node_types) is private; type node is access node_record; subtype character_data is node; subtype element is node (element_node); subtype attr is node (attribute_node); subtype cdata_section is character_data (cdata_section_node); subtype entity_reference is node (entity_reference_node); subtype entity is node (entity_node); subtype processing_instruction is node (processing_instruction_node); subtype text is character_data (text_node); subtype comment is character_data (comment_node); subtype document is node (document_node); subtype document_type is node (document_type_node); subtype document_fragment is node (document_fragment_node); subtype notation is node (notation_node); type node_list is private; -- A simple ordered list of nodes (see DOM.Core.Nodes for subprograms) type named_node_map is private; -- A collection of nodes accessible by their names. -- This is unordered. procedure Free (List : in out node_list); -- Free the memory occupied by the list. The items contained in the list -- are not freed, since they still exist in the XML tree. ------------------------ -- Dom implementation -- ------------------------ -- This provides a number of methods for performing operations that are -- independent of any particular instance of the document object model. type dom_implementation is private; -- There are multiple implementations of DOM. -- They can be specialized for some special cases (HTML, Stylesheets,...) function Has_Feature (Implementation : dom_implementation; Feature : dom_string; Version : String := "2.0") return Boolean; -- Return TRUE if this implementation of DOM has the Feature. function Create_Document (Implementation : dom_implementation; NameSpace_URI : dom_string := ""; Qualified_Name : dom_string := ""; Doc_Type : node := null; Symbols : Sax.Utils.symbol_table := Sax.Utils.No_Symbol_Table) return node; -- Create an new document with its element. -- Note that NameSpace_URI can be the empty string if you do not want -- to use namespaces. -- The Document Type Definition can be null if there is none associated -- with the document. -- Wrong_Document_Err is raised if Doc_Type has already been used for -- another document. -- Symbols should be used to specify the symbol table used by the parser -- that generates the DOM. It is needed because the various string elements -- in the tree are represented as symbols and the correct symbol table must -- be specified. You can get it from the parser itself by using -- Get_Symbol_Table. Optionally, you can pass an explicit No_Symbol_Table -- to create one automatically. It is recommended to share the table with -- the parser whenever possible for maximum efficient. -- In general, the document is created from the Start_Document callback -- of a tree_reader, so the simplest is to call the inherited -- Start_Document. procedure Set_Node_List_Growth_Factor (Factor : Float); -- Set the growth factor, see Default_Node_List_Growth_Factor -------------------- -- Dom exceptions -- -------------------- -- The following exceptions are declared in the DOM interface. If we -- were to follow exactly the interface, we should a single exception to -- which we associate an integer code. It seems easier to provide one -- exception for each case. However, we kept the standard names. Index_Size_Err : exception; -- If Index or size is invalid (negative or greated than max value). Domstring_Size_Err : exception; -- If the specified range of text does not fit into a DomString. Hierarchy_Request_Err : exception; -- If a node is inserted somewhere it doesn't belong. Wrong_Document_Err : exception; -- If a node is used with a document other than its own. Invalid_Character_Err : exception; -- If an invalid character is used, for instance in a name. No_Data_Allowed_Err : exception; -- If data is specified for a node that doesn't support data. No_Modification_Allowed_Err : exception; -- If an attempt is made to modify a read-only object. Not_Found_Err : exception; -- If an attempt is made to reference a node in a concept where it doesn't -- exist. Not_Supported_Err : exception; -- If the implementation does not support the type of object requested. Inuse_Attribute_Err : exception; -- If an attempt is made to add an attribute that is already used. Invalid_State_Err : exception; -- If an attempt is made to use an object that is not or no longer -- available. Syntax_Err : exception; -- If an invalid string is specified. Invalid_Modification_Err : exception; -- If an attempt is made to modify the type of the underlying object. Namespace_Err : exception; -- If an attempt is made to create or modify an object in a way -- incompatible with the namespace. Invalid_Access_Err : exception; -- If a parameter or an operation is not supported by the underlying -- object. private type dom_implementation is null record; type node_array is array (Natural range <>) of node; type node_array_access is access node_array; procedure Free is new Ada.Unchecked_Deallocation (node_array, node_array_access); type node_list is record Items : node_array_access := null; Last : Integer := -1; end record; Null_List : constant node_list := (null, -1); -- Not the most efficient way to implement a hash-table, but these are -- generally short lists anyway (attributes,...) type named_node_map is new node_list; Null_Node_Map : constant named_node_map := (null, -1); ------------------ -- Nodes htable -- ------------------ type node_string is record N : node; Key : Sax.Symbols.symbol; end record; No_Node_String : constant node_string := (null, Sax.Symbols.No_Symbol); procedure Free (N : in out node_string); function Get_Key (N : node_string) return Sax.Symbols.symbol; pragma inline (Free, Get_Key); package Nodes_Htable is new Sax.HTable (element => node_string, Empty_Element => No_Node_String, Free => Free, key => Sax.Symbols.symbol, Get_Key => Get_Key, Hash => Sax.Symbols.Hash, Equal => Sax.Symbols."="); type nodes_htable_access is access Nodes_Htable.htable; ------------------- -- Node_Name_Def -- ------------------- -- Attributes and Elements share the same kind description. These are -- grouped in the same type for ease of use type node_name_def is record Prefix : Sax.Symbols.symbol; Local_Name : Sax.Symbols.symbol; Namespace : Sax.Symbols.symbol; end record; No_Node_Name : constant node_name_def := (Prefix => Sax.Symbols.No_Symbol, Local_Name => Sax.Symbols.No_Symbol, Namespace => Sax.Symbols.No_Symbol); function Qualified_Name (N : node_name_def) return dom_string; pragma inline (Qualified_Name); -- Return the qualified name of N procedure Set_Prefix (N : in out node_name_def; Prefix : Sax.Symbols.symbol); pragma inline (Set_Prefix); -- Return or set the prefix of N function From_Qualified_Name (Doc : document; Symbols : Sax.Utils.symbol_table; Name : Sax.Symbols.symbol; Namespace : Sax.Symbols.symbol := Sax.Symbols.No_Symbol) return node_name_def; -- Build a node name from its qualified name. This is shared if -- Shared_Node_Names is True. -- Symbols is the symbol table in which Name and Namespace were created. ----------------- -- Node_Record -- ----------------- type node_record (Node_Type : node_types) is record Parent_Is_Owner : Boolean; -- If False, the Parent node points to the owner document, not to the -- real parent in the tree (which is null). -- This boolean doesn't increase the size of this record, since because -- of alignment issues Node_Type already occupies more space than it -- really needs. Parent : node; case Node_Type is when element_node => Name : node_name_def; Children : node_list; Attributes : named_node_map; when attribute_node => Attr_Name : node_name_def; Attr_Value : Sax.Symbols.symbol; Owner_Element : node; -- Generally an Element, but it can be a Document if the attribute -- hasn't been associated yet. Is_Id : Boolean := False; Specified : Boolean := False; -- ??? In fact, attributes can have children (text or -- entity_reference). when text_node => Text : dom_string_access; when cdata_section_node => Cdata : dom_string_access; when entity_reference_node => Entity_Reference_Name : Sax.Symbols.symbol; when entity_node => Entity_Name : Sax.Symbols.symbol; -- ??? Allows children for the substitution of the entity when processing_instruction_node => Target : Sax.Symbols.symbol; Pi_Data : Sax.Symbols.symbol; when comment_node => Comment : dom_string_access; when document_node => Symbols : Sax.Utils.symbol_table; -- Keep a handle on the symbol table to ensure the symbols remain -- valid while the tree exists Doc_Children : node_list; Doc_Type : node; Implementation : dom_implementation; Ids : nodes_htable_access; when document_type_node => Document_Type_Name : dom_string_access; Doc_Type_Children : node_list; when document_fragment_node => Doc_Frag_Children : node_list; when notation_node => Public_ID : dom_string_access; System_ID : dom_string_access; end case; end record; procedure Append (List : in out node_list; N : node); -- Insert N as the last element in List procedure Remove (List : in out node_list; N : node); -- Remove N from the list -- N must be an element of List, this is not checked. procedure Document_Add_Id (Doc : document; Id : Sax.Symbols.symbol; Elem : element); -- Store in the document as fast access to Elem by its ID procedure Document_Remove_Id (Doc : document; Id : Sax.Symbols.symbol); -- Remove an ID associated with Elem in the fast htable access end DOM.Core;