------------------------------------------------------------------------------
-- XML/Ada - An XML suite for Ada95 --
-- --
-- Copyright (C) 2004-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 provides a SAX Reader that parses an XML Schema file, and
-- creates the appropriate data structure
pragma Ada_05;
with Input_Sources;
with Sax.Locators;
with Sax.Readers; use Sax.Readers;
with Sax.Symbols;
with Sax.Utils;
with Schema.Readers;
with Schema.Simple_Types;
with Schema.Validators;
with Unicode.CES;
with GNAT.Dynamic_Tables;
with GNAT.Dynamic_HTables;
package Schema.Schema_Readers is
type Schema_Reader is new Schema.Readers.Validating_Reader with private;
type Schema_Reader_Access is access all Schema_Reader'Class;
-- An XML reader that parses an XML schema, and store the information in
-- a grammar
procedure Parse_Grammar
(Handler : access Schema.Readers.Validating_Reader'Class;
URI : Sax.Symbols.Symbol;
Xsd_File : Sax.Symbols.Symbol;
Do_Create_NFA : Boolean);
-- Parse (if not done already) the specified [Xsd_File], and associate it
-- with the given namespace [URI].
-- [Handler] is used to convert [Xsd_File] to an absolute URI, and find
-- the grammar.
overriding procedure Set_Feature
(Parser : in out Schema_Reader; Name : String; Value : Boolean);
overriding function Get_Feature
(Parser : Schema_Reader; Name : String) return Boolean;
-- Add support for new features
Feature_Ignore_Unsupported_XSD_Elements : constant String :=
"http://www.adacore.com/schema/features/ignoreUnsupportedXSDElements";
-- If this feature is true, then elements from an XSD file that are known
-- to be unsupported by XML/Ada (for instance , ,...) will
-- result in a warning, rather than a fatal error.
-- As a user, you are free to ignore these. XML/Ada will simply not provide
-- validation for those elements.
private
use Schema.Validators;
type Internal_Type_Index is new Integer;
No_Internal_Type_Index : constant Internal_Type_Index := -1;
type Type_Kind is (Type_Empty, Type_Sequence, Type_Choice, Type_Element,
Type_Any, Type_Group, Type_Extension, Type_Restriction,
Type_All);
type Type_Details;
type Type_Details_Access is access all Type_Details;
type Element_Descr is record
Name : Qualified_Name := No_Qualified_Name;
Typ : Qualified_Name := No_Qualified_Name;
Local_Type : Internal_Type_Index := No_Internal_Type_Index;
Ref : Qualified_Name := No_Qualified_Name;
Form : Form_Type := Unqualified;
Default : Sax.Symbols.Symbol := Sax.Symbols.No_Symbol;
Fixed : Sax.Symbols.Symbol := Sax.Symbols.No_Symbol;
Substitution_Group : Qualified_Name := No_Qualified_Name;
Final : Final_Status := (others => False);
Block : Block_Status := (others => False);
Is_Abstract : Boolean := False;
Nillable : Boolean := False;
Has_Block : Boolean := False;
Loc : Sax.Locators.Location := Sax.Locators.No_Location;
S : Schema_State_Machines.State :=
Schema_State_Machines.No_State;
end record;
No_Element_Descr : constant Element_Descr := (others => <>);
type Group_Descr is record
Name : Qualified_Name := No_Qualified_Name;
Ref : Qualified_Name := No_Qualified_Name;
Details : Type_Details_Access;
Loc : Sax.Locators.Location;
end record;
No_Group_Descr : constant Group_Descr := (others => <>);
type Internal_Attribute_Descr is record
Descr : Attribute_Descr := No_Attribute_Descr;
Typ : Qualified_Name := No_Qualified_Name;
Local_Type : Internal_Type_Index := No_Internal_Type_Index;
Ref : Qualified_Name := No_Qualified_Name;
Any : Internal_Any_Descr := No_Internal_Any_Descr;
-- For the handling of
end record;
No_Internal_Attribute : constant Internal_Attribute_Descr := (others => <>);
type Attr_Descr_Kind is (Kind_Group, Kind_Attribute, Kind_Unset);
type Attr_Descr (Kind : Attr_Descr_Kind := Kind_Unset) is record
Loc : Sax.Locators.Location := Sax.Locators.No_Location;
case Kind is
when Kind_Unset => null;
when Kind_Group => Group_Ref : Qualified_Name;
when Kind_Attribute => Attr : Internal_Attribute_Descr;
end case;
end record;
type Attr_Array is array (Natural range <>) of Attr_Descr;
type Attr_Array_Access is access all Attr_Array;
type AttrGroup_Descr is record
Name : Qualified_Name := No_Qualified_Name;
Ref : Qualified_Name := No_Qualified_Name;
Attributes : Attr_Array_Access;
end record;
No_AttrGroup_Descr : constant AttrGroup_Descr := (others => <>);
type Extension_Descr is record
Base : Qualified_Name := No_Qualified_Name;
Details : Type_Details_Access;
Loc : Sax.Locators.Location;
end record;
-- Attributes are set in the corresponding Internal_Type_Descr
type Restriction_Descr is record
Base : Qualified_Name := No_Qualified_Name;
Details : Type_Details_Access;
Loc : Sax.Locators.Location;
end record;
-- Attributes are set in the corresponding Internal_Type_Descr
type Type_Details (Kind : Type_Kind := Type_Empty) is record
In_Process : Boolean := False;
-- Set to true while we are creating the NFA for this details. This is
-- used to prevent infinite recursion, for instance when an extension
-- indirectly uses itself as a base.
Loc : Sax.Locators.Location;
Min_Occurs, Max_Occurs : Occurrences;
Next : Type_Details_Access;
case Kind is
when Type_Empty => null;
when Type_Sequence => First_In_Seq : Type_Details_Access;
when Type_Choice => First_In_Choice : Type_Details_Access;
when Type_Element => Element : Element_Descr;
when Type_Any => Any : Internal_Any_Descr;
when Type_Group => Group : Group_Descr;
when Type_Extension =>
Extension : Extension_Descr;
Simple_Content : Boolean;
when Type_Restriction =>
Restriction : Restriction_Descr;
Simple_Content_Restriction : Boolean;
when Type_All => First_In_All : Type_Details_Access;
end case;
end record;
type Type_Member is record
Name : Qualified_Name := No_Qualified_Name;
Local : Internal_Type_Index := No_Internal_Type_Index;
end record;
No_Type_Member : constant Type_Member :=
(No_Qualified_Name, No_Internal_Type_Index);
-- Only one of the two fields is set. These are the possible members of a
-- union or list.
type Type_Member_Array is array (Natural range <>) of Type_Member;
type Simple_Type_Kind is (Simple_Type_None,
Simple_Type,
Simple_Type_Restriction,
Simple_Type_Extension,
Simple_Type_Union,
Simple_Type_List);
type Internal_Simple_Type_Descr (Kind : Simple_Type_Kind := Simple_Type)
is record
In_Process : Boolean := False;
-- Used to prevent infinite recursion when for instance a union's member
-- is derived from this union.
Loc : Sax.Locators.Location := Sax.Locators.No_Location;
case Kind is
when Simple_Type_None => null;
when Simple_Type => null;
when Simple_Type_Union =>
Union_Items : Type_Member_Array
(1 .. Schema.Simple_Types.Max_Types_In_Union) :=
(others => No_Type_Member);
when Simple_Type_List =>
List_Items : Type_Member_Array
(1 .. 1) := (others => No_Type_Member);
when Simple_Type_Restriction | Simple_Type_Extension =>
Base : Type_Member;
Facets : Schema.Simple_Types.All_Facets :=
Schema.Simple_Types.No_Facets;
end case;
end record;
No_Internal_Simple_Type_Descr : constant Internal_Simple_Type_Descr :=
(Kind => Simple_Type_None, others => <>);
subtype Union_Type_Descr is Internal_Simple_Type_Descr (Simple_Type_Union);
subtype List_Type_Descr is Internal_Simple_Type_Descr (Simple_Type_List);
type Internal_Type_Descr (Is_Simple : Boolean := False) is record
Properties : Type_Descr; -- Properties of the type, read in XSD
In_NFA : Type_Index; -- As created in the NFA
Loc : Sax.Locators.Location := Sax.Locators.No_Location;
Simple : Internal_Simple_Type_Descr :=
No_Internal_Simple_Type_Descr;
-- Either the type itself if we are defining a simpleType, or its
-- simpleContent if we are definiting a complexType (in which case its
-- kind might be [Simple_Type_None] to indicate it is a complex content
case Is_Simple is
when False =>
Attributes : Attr_Array_Access;
-- Stores attributes from or the internal
--
Details : Type_Details_Access;
when True =>
null;
end case;
end record;
-- Temporary structure while parsing a XSD file. Only [Descr] will be
-- stored in the NFA for reuse while validating (or while parsing other
-- XSD).
type Schema_Descr is record
Target_NS : Sax.Symbols.Symbol := Sax.Symbols.No_Symbol;
Block : Block_Status := No_Block;
Element_Form_Default : Form_Type := Unqualified;
Attribute_Form_Default : Form_Type := Unqualified;
end record;
type Context_Type is (Context_Type_Def,
Context_Element,
Context_Sequence,
Context_Choice,
Context_Schema,
Context_Restriction,
Context_Simple_Restriction, -- simpleType
Context_Simple_Extension, -- simpleType
Context_Extension,
Context_All,
Context_List,
Context_Union,
Context_Redefine,
Context_Group,
Context_Attribute_Group,
Context_Attribute);
type Context (Typ : Context_Type := Context_Schema) is record
case Typ is
when Context_Type_Def => Type_Info : Internal_Type_Index;
when Context_Element =>
Element : Element_Descr;
Elem_Details : Type_Details_Access;
when Context_Sequence => Seq : Type_Details_Access;
when Context_Choice => Choice : Type_Details_Access;
when Context_All => All_Detail : Type_Details_Access;
when Context_Attribute_Group => Attr_Group : AttrGroup_Descr;
when Context_Schema => null;
when Context_Redefine => null;
when Context_Group => Group : Group_Descr;
when Context_Extension => Extension : Type_Details_Access;
when Context_List => List : List_Type_Descr;
when Context_Restriction => Restriction : Type_Details_Access;
when Context_Simple_Restriction | Context_Simple_Extension =>
Simple : Internal_Simple_Type_Descr;
when Context_Union => Union : Union_Type_Descr;
when Context_Attribute => Attribute : Attr_Descr;
end case;
end record;
type Context_Access is access all Context;
type Context_Array is array (Natural range <>) of aliased Context;
type Context_Array_Access is access all Context_Array;
package Type_Tables is new GNAT.Dynamic_Tables
(Table_Component_Type => Internal_Type_Descr,
Table_Index_Type => Internal_Type_Index,
Table_Low_Bound => 1,
Table_Initial => 200,
Table_Increment => 100);
package Element_HTables is new GNAT.Dynamic_HTables.Simple_HTable
(Header_Num => Header_Num,
Element => Element_Descr,
No_Element => No_Element_Descr,
Key => Qualified_Name,
Hash => Hash,
Equal => "=");
package Group_HTables is new GNAT.Dynamic_HTables.Simple_HTable
(Header_Num => Header_Num,
Element => Group_Descr,
No_Element => No_Group_Descr,
Key => Qualified_Name,
Hash => Hash,
Equal => "=");
package AttrGroup_HTables is new GNAT.Dynamic_HTables.Simple_HTable
(Header_Num => Header_Num,
Element => AttrGroup_Descr,
No_Element => No_AttrGroup_Descr,
Key => Qualified_Name,
Hash => Hash,
Equal => "=");
package Attribute_HTables is new GNAT.Dynamic_HTables.Simple_HTable
(Header_Num => Header_Num,
Element => Internal_Attribute_Descr,
No_Element => No_Internal_Attribute,
Key => Qualified_Name,
Hash => Hash,
Equal => "=");
type XSD_Data is record
Types : Type_Tables.Instance;
Global_Elements : Element_HTables.Instance;
Global_Groups : Group_HTables.Instance;
Global_AttrGroups : AttrGroup_HTables.Instance;
Global_Attributes : Attribute_HTables.Instance;
end record;
type XSD_Data_Access is access all XSD_Data;
-- Data modified while loading XSD, and needed while loading nested (input
-- or redefine) XSD, until we can create the NFA
type Schema_Reader is new Schema.Readers.Validating_Reader with record
Attribute_Form_Default : Schema.Validators.Form_Type :=
Schema.Validators.Unqualified;
Element_Form_Default : Schema.Validators.Form_Type :=
Schema.Validators.Unqualified;
-- The value of elementFormDefault for the current file
Feature_Ignore_Unsupported_XSD_Elements : Boolean := False;
Target_NS : Sax.Symbols.Symbol;
Target_Block_Default : Block_Status := No_Block;
-- The namespace for which we are currently parsing. This might be
-- different from Get_Target_NS (Created_Grammar) when processing
-- for instance.
In_Annotation : Boolean := False;
-- Whether we are processing an node, in which case we
-- need to ignore all children
Contexts : Context_Array_Access;
Contexts_Last : Natural := 0;
Shared : XSD_Data_Access;
end record;
overriding procedure Start_Element
(Handler : in out Schema_Reader;
NS : Sax.Utils.XML_NS;
Local_Name : Sax.Symbols.Symbol;
Atts : Sax.Readers.Sax_Attribute_List);
overriding procedure End_Element
(Handler : in out Schema_Reader;
NS : Sax.Utils.XML_NS;
Local_Name : Sax.Symbols.Symbol);
overriding procedure Characters
(Handler : in out Schema_Reader; Ch : Unicode.CES.Byte_Sequence);
overriding procedure Parse
(Parser : in out Schema_Reader;
Input : in out Input_Sources.Input_Source'Class);
-- See inherited documentation
end Schema.Schema_Readers;