2007-09-09 22:30:50 +00:00
|
|
|
{
|
|
|
|
This file is part of the Web Service Toolkit
|
|
|
|
Copyright (c) 2007 by Inoussa OUEDRAOGO
|
|
|
|
|
|
|
|
This file is provide under modified LGPL licence
|
|
|
|
( the files COPYING.modifiedLGPL and COPYING.LGPL).
|
|
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
}
|
|
|
|
{$INCLUDE wst_global.inc}
|
|
|
|
unit xsd_parser;
|
|
|
|
|
|
|
|
interface
|
|
|
|
uses
|
|
|
|
Classes, SysUtils,
|
|
|
|
{$IFNDEF FPC}xmldom, wst_delphi_xml{$ELSE}DOM{$ENDIF},
|
|
|
|
cursor_intf, rtti_filters,
|
|
|
|
pastree, pascal_parser_intf, logger_intf;
|
|
|
|
|
|
|
|
type
|
|
|
|
|
|
|
|
EXsdParserException = class(Exception)
|
|
|
|
end;
|
|
|
|
|
|
|
|
EXsdParserAssertException = class(EXsdParserException)
|
|
|
|
end;
|
|
|
|
|
|
|
|
EXsdTypeNotFoundException = class(EXsdParserException)
|
|
|
|
end;
|
|
|
|
|
|
|
|
EXsdInvalidDefinitionException = class(EXsdParserException)
|
|
|
|
end;
|
|
|
|
|
|
|
|
EXsdInvalidTypeDefinitionException = class(EXsdInvalidDefinitionException)
|
|
|
|
end;
|
|
|
|
|
|
|
|
EXsdInvalidElementDefinitionException = class(EXsdInvalidDefinitionException)
|
|
|
|
end;
|
|
|
|
|
|
|
|
TOnParserMessage = procedure (const AMsgType : TMessageType; const AMsg : string) of object;
|
|
|
|
|
2009-11-23 17:55:10 +00:00
|
|
|
IDocumentLocator = interface
|
|
|
|
['{F063700B-C0ED-4C54-9A54-C97030E80BD4}']
|
|
|
|
function Find(
|
|
|
|
const ADocLocation : string;
|
|
|
|
out ADoc : TXMLDocument
|
|
|
|
) : Boolean;
|
2011-08-29 02:59:57 +00:00
|
|
|
function FindPath(ADocLocation : string) : string;
|
|
|
|
|
|
|
|
function GetBasePath() : string;
|
|
|
|
procedure SetBasePath(AValue : string);
|
|
|
|
function Clone() : IDocumentLocator;
|
2009-11-23 17:55:10 +00:00
|
|
|
end;
|
2007-09-09 22:30:50 +00:00
|
|
|
|
2009-11-26 10:39:50 +00:00
|
|
|
TParserOption = (
|
2011-08-29 02:59:57 +00:00
|
|
|
poEnumAlwaysPrefix, // Always prefix enum item with the enum name
|
|
|
|
poParsingIncludeSchema
|
2009-11-26 10:39:50 +00:00
|
|
|
);
|
|
|
|
TParserOptions = set of TParserOption;
|
2007-09-09 22:30:50 +00:00
|
|
|
IParserContext = interface
|
|
|
|
['{F400BA9E-41AC-456C-ABF9-CEAA75313685}']
|
|
|
|
function GetXsShortNames() : TStrings;
|
|
|
|
function GetSymbolTable() : TwstPasTreeContainer;
|
|
|
|
function FindNameSpace(const AShortName : string; out AResult : string) : Boolean;
|
|
|
|
function FindShortNamesForNameSpace(const ANameSpace : string) : TStrings;
|
|
|
|
function GetTargetNameSpace() : string;
|
|
|
|
function GetTargetModule() : TPasModule;
|
2009-11-23 17:55:10 +00:00
|
|
|
function GetDocumentLocator() : IDocumentLocator;
|
2011-08-29 02:59:57 +00:00
|
|
|
procedure SetDocumentLocator(ALocator : IDocumentLocator);
|
2009-11-26 10:39:50 +00:00
|
|
|
function GetSimpleOptions() : TParserOptions;
|
|
|
|
procedure SetSimpleOptions(const AValue : TParserOptions);
|
2013-11-19 11:04:25 +00:00
|
|
|
procedure AddTypeToCheck(AType : TPasType);
|
2011-08-29 02:59:57 +00:00
|
|
|
|
|
|
|
procedure AddIncludedDoc(ADocLocation : string);
|
|
|
|
function IsIncludedDoc(ADocLocation : string) : Boolean;
|
2007-09-09 22:30:50 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
IXsdPaser = interface
|
|
|
|
['{F0CEC726-A068-4CCC-B1E7-D31F018415B2}']
|
2010-10-11 12:28:07 +00:00
|
|
|
function FindParser(const ANamespace : string) : IXsdPaser;
|
2009-09-02 12:24:19 +00:00
|
|
|
function ParseType(
|
|
|
|
const AName,
|
|
|
|
ATypeKind : string { ATypeKind "ComplexType", "SimpleType", "Element" }
|
|
|
|
) : TPasType; overload;
|
|
|
|
function ParseType(
|
|
|
|
const AName : string;
|
|
|
|
const ATypeNode : TDOMNode
|
|
|
|
) : TPasType; overload;
|
2007-09-09 22:30:50 +00:00
|
|
|
procedure ParseTypes();
|
|
|
|
procedure SetNotifier(ANotifier : TOnParserMessage);
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ TCustomXsdSchemaParser }
|
|
|
|
|
|
|
|
TCustomXsdSchemaParser = class(TInterfacedObject, IInterface, IParserContext, IXsdPaser)
|
|
|
|
private
|
|
|
|
FDoc : TXMLDocument;
|
|
|
|
FParentContext : Pointer;//IParserContext;
|
|
|
|
FSymbols : TwstPasTreeContainer;
|
|
|
|
FModuleName : string;
|
|
|
|
FModule : TPasModule;
|
|
|
|
FTargetNameSpace : string;
|
|
|
|
FSchemaNode : TDOMNode;
|
|
|
|
private
|
|
|
|
FNameSpaceList : TStringList;
|
|
|
|
FXSShortNames : TStrings;
|
|
|
|
FChildCursor : IObjectCursor;
|
|
|
|
FOnMessage: TOnParserMessage;
|
2009-11-23 17:55:10 +00:00
|
|
|
FDocumentLocator : IDocumentLocator;
|
2009-11-26 10:39:50 +00:00
|
|
|
FSimpleOptions : TParserOptions;
|
2013-11-19 11:04:25 +00:00
|
|
|
FCheckedTypes : TList2;
|
2009-11-23 17:55:10 +00:00
|
|
|
FImportParsed : Boolean;
|
2010-10-11 12:28:07 +00:00
|
|
|
FXsdParsers : TStringList;
|
2011-08-29 02:59:57 +00:00
|
|
|
FIncludeList : TStringList;
|
|
|
|
FIncludeParsed : Boolean;
|
|
|
|
FPrepared : Boolean;
|
2011-09-16 00:56:48 +00:00
|
|
|
FOldNameKinds : TElementNameKinds;
|
2007-09-09 22:30:50 +00:00
|
|
|
private
|
|
|
|
procedure DoOnMessage(const AMsgType : TMessageType; const AMsg : string);
|
|
|
|
private
|
|
|
|
function FindNamedNode(AList : IObjectCursor; const AName : WideString; const AOrder : Integer = 0):TDOMNode;
|
|
|
|
function GetParentContext() : IParserContext;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
2013-11-19 11:04:25 +00:00
|
|
|
function HasParentContext() : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
2011-08-29 02:59:57 +00:00
|
|
|
procedure Prepare(const AMustSucceed : Boolean);
|
2011-09-16 00:56:48 +00:00
|
|
|
function FindElement(const AName: String) : TPasElement; overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
|
|
function FindElement(const AName: String; const ANameKinds : TElementNameKinds) : TPasElement; overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
2007-09-09 22:30:50 +00:00
|
|
|
protected
|
|
|
|
function GetXsShortNames() : TStrings;
|
|
|
|
function GetSymbolTable() : TwstPasTreeContainer;
|
|
|
|
function FindNameSpace(const AShortName : string; out AResult : string) : Boolean;
|
|
|
|
function FindShortNamesForNameSpaceLocal(const ANameSpace : string) : TStrings;
|
|
|
|
function FindShortNamesForNameSpace(const ANameSpace : string) : TStrings;
|
2009-11-23 17:55:10 +00:00
|
|
|
function GetDocumentLocator() : IDocumentLocator;
|
2011-08-29 02:59:57 +00:00
|
|
|
procedure SetDocumentLocator(ALocator : IDocumentLocator);
|
2009-11-26 10:39:50 +00:00
|
|
|
function GetSimpleOptions() : TParserOptions;
|
|
|
|
procedure SetSimpleOptions(const AValue : TParserOptions);
|
2013-11-19 11:04:25 +00:00
|
|
|
procedure AddTypeToCheck(AType : TPasType);
|
2011-08-29 02:59:57 +00:00
|
|
|
procedure AddIncludedDoc(ADocLocation : string);
|
|
|
|
function IsIncludedDoc(ADocLocation : string) : Boolean;
|
2009-11-23 17:55:10 +00:00
|
|
|
|
2007-09-09 22:30:50 +00:00
|
|
|
procedure SetNotifier(ANotifier : TOnParserMessage);
|
2009-09-02 12:24:19 +00:00
|
|
|
function InternalParseType(
|
|
|
|
const AName : string;
|
|
|
|
const ATypeNode : TDOMNode
|
|
|
|
) : TPasType;
|
2010-10-11 12:28:07 +00:00
|
|
|
procedure CreateImportParsers();
|
2009-11-23 17:55:10 +00:00
|
|
|
procedure ParseImportDocuments(); virtual;
|
2011-08-29 02:59:57 +00:00
|
|
|
procedure CreateIncludeList();
|
|
|
|
procedure ParseIncludeDocuments(); virtual;
|
2007-09-09 22:30:50 +00:00
|
|
|
public
|
|
|
|
constructor Create(
|
|
|
|
ADoc : TXMLDocument;
|
|
|
|
ASchemaNode : TDOMNode;
|
|
|
|
ASymbols : TwstPasTreeContainer;
|
|
|
|
AParentContext : IParserContext
|
2009-11-23 17:55:10 +00:00
|
|
|
); virtual;
|
2007-09-09 22:30:50 +00:00
|
|
|
destructor Destroy();override;
|
2010-10-11 12:28:07 +00:00
|
|
|
function FindParser(const ANamespace : string) : IXsdPaser;
|
2009-09-02 12:24:19 +00:00
|
|
|
function ParseType(
|
|
|
|
const AName,
|
|
|
|
ATypeKind : string { ATypeKind "ComplexType", "SimpleType", "Element" }
|
|
|
|
) : TPasType; overload;
|
|
|
|
function ParseType(
|
|
|
|
const AName : string;
|
|
|
|
const ATypeNode : TDOMNode
|
|
|
|
) : TPasType; overload;
|
|
|
|
|
2007-09-09 22:30:50 +00:00
|
|
|
procedure ParseTypes();
|
|
|
|
|
|
|
|
function GetTargetNameSpace() : string;
|
|
|
|
function GetTargetModule() : TPasModule;
|
|
|
|
|
|
|
|
property SymbolTable : TwstPasTreeContainer read FSymbols;
|
|
|
|
property Module : TPasModule read FModule;
|
|
|
|
property OnMessage : TOnParserMessage read FOnMessage write FOnMessage;
|
|
|
|
end;
|
2009-11-23 17:55:10 +00:00
|
|
|
TCustomXsdSchemaParserClass = class of TCustomXsdSchemaParser;
|
2007-09-09 22:30:50 +00:00
|
|
|
|
|
|
|
TXsdParser = class(TCustomXsdSchemaParser)
|
|
|
|
public
|
|
|
|
constructor Create(
|
|
|
|
ADoc : TXMLDocument;
|
|
|
|
ASymbols : TwstPasTreeContainer;
|
2008-09-10 01:46:45 +00:00
|
|
|
const AModuleName : string;
|
|
|
|
const ANotifier : TOnParserMessage = nil
|
2007-09-09 22:30:50 +00:00
|
|
|
);
|
|
|
|
end;
|
|
|
|
|
2013-11-19 11:04:25 +00:00
|
|
|
procedure CheckDuplicatedProperties(
|
|
|
|
AClassList : TList2;
|
|
|
|
ASymbolTable : TwstPasTreeContainer
|
|
|
|
);
|
|
|
|
|
2007-09-09 22:30:50 +00:00
|
|
|
implementation
|
2010-10-16 18:38:07 +00:00
|
|
|
uses ws_parser_imp, dom_cursors, parserutils, xsd_consts, wst_consts
|
2007-09-09 22:30:50 +00:00
|
|
|
{$IFDEF FPC}
|
|
|
|
,wst_fpc_xml
|
|
|
|
{$ENDIF}
|
|
|
|
;
|
|
|
|
|
2009-11-23 17:55:10 +00:00
|
|
|
function NodeValue(const ANode : TDOMNode) : DOMString;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
|
|
begin
|
|
|
|
if ( ANode = nil ) then
|
|
|
|
Result := ''
|
|
|
|
else
|
|
|
|
Result := ANode.NodeValue;
|
|
|
|
end;
|
|
|
|
|
2013-11-19 11:04:25 +00:00
|
|
|
procedure CheckDuplicatedProperties(
|
|
|
|
AClassList : TList2;
|
|
|
|
ASymbolTable : TwstPasTreeContainer
|
|
|
|
);
|
|
|
|
var
|
|
|
|
i, k : Integer;
|
|
|
|
locItem : TPasClassType;
|
|
|
|
locAncestor : TPasType;
|
|
|
|
e : TPasElement;
|
|
|
|
begin
|
|
|
|
for i := 0 to AClassList.Count-1 do begin
|
|
|
|
locItem := TPasClassType(AClassList[i]);
|
|
|
|
if (locItem.Members.Count = 0) then
|
|
|
|
Continue;
|
|
|
|
locAncestor := locItem.AncestorType;
|
|
|
|
while (locAncestor <> nil) do begin
|
|
|
|
if locAncestor.InheritsFrom(TPasUnresolvedTypeRef) then begin
|
|
|
|
e := ASymbolTable.FindElement(ASymbolTable.GetExternalName(locAncestor));
|
|
|
|
if (e = nil) or not(e.InheritsFrom(TPasType)) then
|
|
|
|
Break;
|
|
|
|
locAncestor := e as TPasType;
|
|
|
|
end;
|
|
|
|
if not locAncestor.InheritsFrom(TPasClassType) then
|
|
|
|
Break;
|
|
|
|
if (TPasClassType(locAncestor).Members.Count = 0) then
|
|
|
|
Break;
|
|
|
|
k := 0;
|
|
|
|
while (k < locItem.Members.Count) do begin
|
|
|
|
e := TPasElement(locItem.Members[k]);
|
|
|
|
if not e.InheritsFrom(TPasProperty) then
|
|
|
|
Continue;
|
|
|
|
if (TPasClassType(locAncestor).FindMember(TPasProperty,e.Name) <> nil) then begin
|
|
|
|
locItem.Members.Delete(k);
|
|
|
|
e.Release();
|
|
|
|
Continue;
|
|
|
|
end;
|
|
|
|
k := k + 1;
|
|
|
|
end;
|
|
|
|
locAncestor := TPasClassType(locAncestor).AncestorType;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
2007-09-09 22:30:50 +00:00
|
|
|
{ TCustomXsdSchemaParser }
|
|
|
|
|
|
|
|
constructor TCustomXsdSchemaParser.Create(
|
|
|
|
ADoc : TXMLDocument;
|
|
|
|
ASchemaNode : TDOMNode;
|
|
|
|
ASymbols : TwstPasTreeContainer;
|
|
|
|
AParentContext : IParserContext
|
|
|
|
);
|
|
|
|
begin
|
|
|
|
if ( ADoc = nil ) then
|
2010-10-16 18:38:07 +00:00
|
|
|
raise EXsdParserAssertException.Create(SERR_InvalidDomDocument);
|
2007-09-09 22:30:50 +00:00
|
|
|
if ( ASchemaNode = nil ) then
|
2010-10-16 18:38:07 +00:00
|
|
|
raise EXsdParserAssertException.Create(SERR_InvalidSchemaNode);
|
2007-09-09 22:30:50 +00:00
|
|
|
if ( ASymbols = nil ) then
|
2010-10-16 18:38:07 +00:00
|
|
|
raise EXsdParserAssertException.Create(SERR_InvalidSymbolTable);
|
2007-09-09 22:30:50 +00:00
|
|
|
|
|
|
|
FDoc := ADoc;
|
|
|
|
FParentContext := Pointer(AParentContext);
|
|
|
|
FSymbols := ASymbols;
|
2011-09-16 00:56:48 +00:00
|
|
|
FOldNameKinds := FSymbols.DefaultSearchNameKinds;
|
|
|
|
FSymbols.DefaultSearchNameKinds := [elkDeclaredName];
|
2007-09-09 22:30:50 +00:00
|
|
|
FSchemaNode := ASchemaNode;
|
|
|
|
|
|
|
|
FNameSpaceList := TStringList.Create();
|
|
|
|
FNameSpaceList.Duplicates := dupError;
|
|
|
|
FNameSpaceList.Sorted := True;
|
|
|
|
|
2011-08-29 02:59:57 +00:00
|
|
|
Prepare(False);
|
2007-09-09 22:30:50 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
destructor TCustomXsdSchemaParser.Destroy();
|
2010-10-11 12:28:07 +00:00
|
|
|
|
|
|
|
procedure FreeList(AList : TStrings);
|
|
|
|
var
|
|
|
|
j : PtrInt;
|
|
|
|
begin
|
2011-11-15 19:11:17 +00:00
|
|
|
if Assigned(AList) and (AList.Count > 0) then begin
|
|
|
|
for j := Pred(AList.Count) downto 0 do begin
|
2010-10-11 12:28:07 +00:00
|
|
|
AList.Objects[j].Free();
|
|
|
|
AList.Objects[j] := nil;
|
|
|
|
end;
|
|
|
|
AList.Free();
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
begin
|
2011-09-16 00:56:48 +00:00
|
|
|
if (FSymbols <> nil) then
|
|
|
|
FSymbols.DefaultSearchNameKinds := FOldNameKinds;
|
2010-10-11 12:28:07 +00:00
|
|
|
FParentContext := nil;
|
2011-08-29 02:59:57 +00:00
|
|
|
FreeAndNil(FIncludeList);
|
2010-10-11 12:28:07 +00:00
|
|
|
FreeList(FNameSpaceList);
|
2013-11-19 11:04:25 +00:00
|
|
|
FreeList(FXsdParsers);
|
|
|
|
FCheckedTypes.Free();
|
2010-10-11 12:28:07 +00:00
|
|
|
inherited;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TCustomXsdSchemaParser.FindParser(const ANamespace : string) : IXsdPaser;
|
2007-09-09 22:30:50 +00:00
|
|
|
var
|
|
|
|
i : PtrInt;
|
2010-10-11 12:28:07 +00:00
|
|
|
p, p1 : IXsdPaser;
|
2007-09-09 22:30:50 +00:00
|
|
|
begin
|
2011-08-29 02:59:57 +00:00
|
|
|
Prepare(True);
|
2010-10-11 12:28:07 +00:00
|
|
|
Result := nil;
|
|
|
|
if (ANamespace = FTargetNameSpace) then begin
|
|
|
|
Result := Self;
|
|
|
|
Exit;
|
2007-09-09 22:30:50 +00:00
|
|
|
end;
|
2010-10-11 12:28:07 +00:00
|
|
|
if (FXsdParsers = nil) then
|
|
|
|
CreateImportParsers();
|
|
|
|
if (FXsdParsers = nil) then
|
|
|
|
Exit;
|
|
|
|
i := FXsdParsers.IndexOf(ANamespace);
|
|
|
|
if ( i >= 0 ) then begin
|
|
|
|
Result := (FXsdParsers.Objects[i] as TIntfObjectRef).Intf as IXsdPaser;
|
|
|
|
end else begin
|
|
|
|
for i := 0 to Pred(FXsdParsers.Count) do begin
|
|
|
|
p := (FXsdParsers.Objects[i] as TIntfObjectRef).Intf as IXsdPaser;
|
|
|
|
p1 := p.FindParser(ANamespace);
|
|
|
|
if (p1 <> nil) then begin
|
|
|
|
Result := p1;
|
|
|
|
Break;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
2007-09-09 22:30:50 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TCustomXsdSchemaParser.DoOnMessage(
|
|
|
|
const AMsgType: TMessageType;
|
|
|
|
const AMsg: string
|
|
|
|
);
|
|
|
|
begin
|
|
|
|
if Assigned(FOnMessage) then begin
|
|
|
|
FOnMessage(AMsgType,AMsg);
|
|
|
|
end else if IsConsole and HasLogger() then begin
|
|
|
|
GetLogger().Log(AMsgType, AMsg);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TCustomXsdSchemaParser.FindElement(const AName: String): TPasElement;
|
|
|
|
begin
|
|
|
|
Result := SymbolTable.FindElementInModule(AName,FModule);
|
2007-10-19 15:30:20 +00:00
|
|
|
if ( Result = nil ) then
|
|
|
|
Result := SymbolTable.FindElement(AName);
|
2007-09-09 22:30:50 +00:00
|
|
|
end;
|
|
|
|
|
2011-09-16 00:56:48 +00:00
|
|
|
function TCustomXsdSchemaParser.FindElement(
|
|
|
|
const AName : String;
|
|
|
|
const ANameKinds : TElementNameKinds
|
|
|
|
) : TPasElement;
|
|
|
|
begin
|
|
|
|
Result := SymbolTable.FindElementInModule(AName,FModule,ANameKinds);
|
|
|
|
if ( Result = nil ) then
|
|
|
|
Result := SymbolTable.FindElement(AName,ANameKinds);
|
|
|
|
end;
|
|
|
|
|
2009-11-23 17:55:10 +00:00
|
|
|
procedure TCustomXsdSchemaParser.ParseImportDocuments();
|
|
|
|
var
|
2010-10-11 12:28:07 +00:00
|
|
|
locOldCurrentModule : TPasModule;
|
|
|
|
i : Integer;
|
|
|
|
p : IXsdPaser;
|
2009-11-23 17:55:10 +00:00
|
|
|
begin
|
|
|
|
if FImportParsed then
|
|
|
|
Exit;
|
2010-10-11 12:28:07 +00:00
|
|
|
CreateImportParsers();
|
|
|
|
if (FXsdParsers = nil) then
|
2009-11-23 17:55:10 +00:00
|
|
|
Exit;
|
|
|
|
|
|
|
|
FImportParsed := True;
|
|
|
|
if Assigned(FChildCursor) then begin
|
|
|
|
locOldCurrentModule := SymbolTable.CurrentModule;
|
|
|
|
try
|
2010-10-11 12:28:07 +00:00
|
|
|
for i := 0 to FXsdParsers.Count - 1 do begin
|
|
|
|
p := TIntfObjectRef(FXsdParsers.Objects[i]).Intf as IXsdPaser;
|
|
|
|
p.ParseTypes();
|
2009-11-23 17:55:10 +00:00
|
|
|
end;
|
|
|
|
finally
|
|
|
|
SymbolTable.SetCurrentModule(locOldCurrentModule);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2011-08-29 02:59:57 +00:00
|
|
|
procedure TCustomXsdSchemaParser.CreateIncludeList();
|
|
|
|
begin
|
|
|
|
if (FIncludeList = nil) then begin
|
|
|
|
FIncludeList := TStringList.Create();
|
|
|
|
FIncludeList.Duplicates := dupIgnore;
|
|
|
|
FIncludeList.Sorted := True;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TCustomXsdSchemaParser.ParseIncludeDocuments();
|
|
|
|
var
|
|
|
|
crsSchemaChild : IObjectCursor;
|
|
|
|
strFilter, locFileName : string;
|
|
|
|
includeNode : TDOMElement;
|
|
|
|
includeDoc : TXMLDocument;
|
|
|
|
locParser : IXsdPaser;
|
|
|
|
locOldCurrentModule : TPasModule;
|
|
|
|
locLocator, locTempLocator : IDocumentLocator;
|
|
|
|
locContext : IParserContext;
|
2011-11-26 17:54:55 +00:00
|
|
|
locUsesList : TList2;
|
2011-08-29 02:59:57 +00:00
|
|
|
locModule : TPasModule;
|
|
|
|
locName, s : string;
|
|
|
|
i : Integer;
|
|
|
|
begin
|
|
|
|
if FIncludeParsed then
|
|
|
|
exit;
|
|
|
|
Prepare(True);
|
|
|
|
if (poParsingIncludeSchema in FSimpleOptions) then begin
|
|
|
|
locContext := GetParentContext();
|
|
|
|
if (locContext = nil) then
|
|
|
|
raise EXsdParserAssertException.CreateFmt(SERR_InvalidParserState,['"poParsingIncludeSchema" require a parent context']);
|
|
|
|
if not(IsStrEmpty(FTargetNameSpace)) and (FTargetNameSpace <> locContext.GetTargetNameSpace()) then
|
|
|
|
raise EXsdParserAssertException.Create(SERR_InvalidIncludeDirectiveNS);
|
|
|
|
end;
|
|
|
|
|
|
|
|
FIncludeParsed := True;
|
|
|
|
locLocator := GetDocumentLocator();
|
|
|
|
if (locLocator = nil) then
|
|
|
|
Exit;
|
|
|
|
|
|
|
|
if Assigned(FChildCursor) then begin
|
|
|
|
locOldCurrentModule := SymbolTable.CurrentModule;
|
|
|
|
try
|
|
|
|
locUsesList := FModule.InterfaceSection.UsesList;
|
|
|
|
crsSchemaChild := FChildCursor.Clone() as IObjectCursor;
|
|
|
|
strFilter := CreateQualifiedNameFilterStr(s_include,FXSShortNames);
|
|
|
|
crsSchemaChild := CreateCursorOn(crsSchemaChild,ParseFilter(strFilter,TDOMNodeRttiExposer));
|
|
|
|
crsSchemaChild.Reset();
|
|
|
|
while crsSchemaChild.MoveNext() do begin
|
|
|
|
includeNode := (crsSchemaChild.GetCurrent() as TDOMNodeRttiExposer).InnerObject as TDOMElement;
|
|
|
|
if (includeNode.Attributes <> nil) and (includeNode.Attributes.Length > 0) then begin
|
|
|
|
locFileName := NodeValue(includeNode.Attributes.GetNamedItem(s_schemaLocation));
|
|
|
|
if not(IsStrEmpty(locFileName) or IsIncludedDoc(locFileName)) then begin
|
|
|
|
if locLocator.Find(locFileName,includeDoc) then begin
|
|
|
|
AddIncludedDoc(locFileName);
|
|
|
|
locParser := TCustomXsdSchemaParserClass(Self.ClassType).Create(
|
|
|
|
includeDoc,
|
|
|
|
includeDoc.DocumentElement,
|
|
|
|
SymbolTable,
|
|
|
|
Self as IParserContext
|
|
|
|
);
|
|
|
|
locContext := locParser as IParserContext;
|
|
|
|
locContext.SetSimpleOptions(locContext.GetSimpleOptions() + [poParsingIncludeSchema]);
|
|
|
|
locTempLocator := locLocator.Clone();
|
|
|
|
locTempLocator.SetBasePath(locLocator.FindPath(locFileName));
|
|
|
|
locContext.SetDocumentLocator(locTempLocator);
|
|
|
|
locParser.SetNotifier(FOnMessage);
|
|
|
|
locParser.ParseTypes();
|
|
|
|
locModule := locContext.GetTargetModule();
|
|
|
|
if (ExtractIdentifier(locContext.GetTargetNameSpace()) = locModule.Name) then begin
|
|
|
|
s := ChangeFileExt(ExtractFileName(locFileName),'');
|
|
|
|
i := 1;
|
|
|
|
locName := s;
|
|
|
|
while (FSymbols.FindModule(locName) <> nil) do begin
|
|
|
|
locName := Format('%s%d',[s,i]);
|
|
|
|
Inc(i);
|
|
|
|
end;
|
|
|
|
locModule.Name := locName;
|
|
|
|
end;
|
|
|
|
if (locModule <> FModule) and (locUsesList.IndexOf(locModule) = -1) then begin
|
|
|
|
locModule.AddRef();
|
|
|
|
locUsesList.Add(locModule);
|
|
|
|
end;
|
|
|
|
end else begin
|
|
|
|
DoOnMessage(mtError,Format(SERR_FileNotFound,[locFileName]));
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
finally
|
|
|
|
SymbolTable.SetCurrentModule(locOldCurrentModule);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2007-09-09 22:30:50 +00:00
|
|
|
function TCustomXsdSchemaParser.FindNamedNode(
|
|
|
|
AList : IObjectCursor;
|
|
|
|
const AName : WideString;
|
|
|
|
const AOrder : Integer
|
|
|
|
): TDOMNode;
|
|
|
|
var
|
|
|
|
attCrs, crs : IObjectCursor;
|
|
|
|
curObj : TDOMNodeRttiExposer;
|
|
|
|
fltr : IObjectFilter;
|
|
|
|
locOrder : Integer;
|
|
|
|
begin
|
|
|
|
Result := nil;
|
|
|
|
if Assigned(AList) then begin
|
|
|
|
fltr := ParseFilter(Format('%s = %s',[s_NODE_NAME,QuotedStr(s_name)]),TDOMNodeRttiExposer);
|
|
|
|
AList.Reset();
|
|
|
|
locOrder := AOrder;
|
|
|
|
while AList.MoveNext() do begin
|
|
|
|
curObj := AList.GetCurrent() as TDOMNodeRttiExposer;
|
|
|
|
attCrs := CreateAttributesCursor(curObj.InnerObject,cetRttiNode);
|
|
|
|
if Assigned(attCrs) then begin
|
|
|
|
crs := CreateCursorOn(attCrs,fltr);
|
|
|
|
crs.Reset();
|
|
|
|
if crs.MoveNext() and AnsiSameText(AName,TDOMNodeRttiExposer(crs.GetCurrent()).NodeValue) then begin
|
|
|
|
Dec(locOrder);
|
|
|
|
if ( locOrder <= 0 ) then begin
|
|
|
|
Result := curObj.InnerObject;
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TCustomXsdSchemaParser.FindNameSpace(
|
|
|
|
const AShortName : string;
|
|
|
|
out AResult : string
|
|
|
|
) : Boolean;
|
|
|
|
var
|
|
|
|
i : PtrInt;
|
|
|
|
ls : TStrings;
|
2009-11-16 09:25:37 +00:00
|
|
|
pc : IParserContext;
|
2007-09-09 22:30:50 +00:00
|
|
|
begin
|
|
|
|
AResult := '';
|
|
|
|
Result := False;
|
|
|
|
for i := 0 to Pred(FNameSpaceList.Count) do begin
|
|
|
|
ls := FNameSpaceList.Objects[i] as TStrings;
|
|
|
|
if ( ls.IndexOf(AShortName) >= 0 ) then begin
|
|
|
|
AResult := FNameSpaceList[i];
|
|
|
|
Result := True;
|
|
|
|
Break;
|
|
|
|
end;
|
|
|
|
end;
|
2009-11-16 09:25:37 +00:00
|
|
|
if not Result then begin
|
|
|
|
pc := GetParentContext();
|
|
|
|
if ( pc <> nil ) then
|
|
|
|
Result := GetParentContext().FindNameSpace(AShortName,AResult);
|
|
|
|
end;
|
2007-09-09 22:30:50 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
function TCustomXsdSchemaParser.FindShortNamesForNameSpace(const ANameSpace: string): TStrings;
|
|
|
|
var
|
|
|
|
prtCtx : IParserContext;
|
|
|
|
begin
|
|
|
|
Result := FindShortNamesForNameSpaceLocal(ANameSpace);
|
|
|
|
if ( Result = nil ) then begin
|
|
|
|
prtCtx := GetParentContext();
|
|
|
|
if Assigned(prtCtx) then
|
|
|
|
Result := prtCtx.FindShortNamesForNameSpace(ANameSpace);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2009-11-23 17:55:10 +00:00
|
|
|
function TCustomXsdSchemaParser.GetDocumentLocator(): IDocumentLocator;
|
|
|
|
begin
|
|
|
|
Result := FDocumentLocator;
|
2010-10-11 12:28:07 +00:00
|
|
|
if (Result = nil) and (FParentContext <> nil) then
|
|
|
|
Result := GetParentContext().GetDocumentLocator();
|
2009-11-23 17:55:10 +00:00
|
|
|
end;
|
|
|
|
|
2011-08-29 02:59:57 +00:00
|
|
|
procedure TCustomXsdSchemaParser.SetDocumentLocator(ALocator: IDocumentLocator);
|
2009-11-23 17:55:10 +00:00
|
|
|
begin
|
|
|
|
FDocumentLocator := ALocator;
|
|
|
|
end;
|
|
|
|
|
2009-11-26 10:39:50 +00:00
|
|
|
function TCustomXsdSchemaParser.GetSimpleOptions(): TParserOptions;
|
|
|
|
begin
|
|
|
|
Result := FSimpleOptions;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TCustomXsdSchemaParser.SetSimpleOptions(const AValue: TParserOptions);
|
|
|
|
begin
|
|
|
|
if ( AValue <> FSimpleOptions ) then
|
|
|
|
FSimpleOptions := AValue;
|
|
|
|
end;
|
|
|
|
|
2013-11-19 11:04:25 +00:00
|
|
|
procedure TCustomXsdSchemaParser.AddTypeToCheck(AType: TPasType);
|
|
|
|
begin
|
|
|
|
if (AType = nil) then
|
|
|
|
exit;
|
|
|
|
if HasParentContext() then begin
|
|
|
|
GetParentContext().AddTypeToCheck(AType);
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
if (FCheckedTypes = nil) then
|
|
|
|
FCheckedTypes := TList2.Create();
|
|
|
|
if (FCheckedTypes.IndexOf(AType) = -1) then
|
|
|
|
FCheckedTypes.Add(AType);
|
|
|
|
end;
|
|
|
|
|
2011-08-29 02:59:57 +00:00
|
|
|
procedure TCustomXsdSchemaParser.AddIncludedDoc(ADocLocation : string);
|
|
|
|
begin
|
|
|
|
if (poParsingIncludeSchema in FSimpleOptions) then begin
|
|
|
|
GetParentContext().AddIncludedDoc(ADocLocation);
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
|
|
|
|
if (FIncludeList = nil) then
|
|
|
|
CreateIncludeList();
|
|
|
|
FIncludeList.Add(ADocLocation);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TCustomXsdSchemaParser.IsIncludedDoc(ADocLocation : string) : Boolean;
|
|
|
|
begin
|
|
|
|
Result := False;
|
|
|
|
if (poParsingIncludeSchema in FSimpleOptions) then
|
|
|
|
Result := GetParentContext().IsIncludedDoc(ADocLocation);
|
|
|
|
if not Result then
|
|
|
|
Result := (FIncludeList <> nil) and (FIncludeList.IndexOf(ADocLocation) <> -1);
|
|
|
|
end;
|
|
|
|
|
2007-09-09 22:30:50 +00:00
|
|
|
procedure TCustomXsdSchemaParser.SetNotifier(ANotifier: TOnParserMessage);
|
|
|
|
begin
|
|
|
|
FOnMessage := ANotifier;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TCustomXsdSchemaParser.FindShortNamesForNameSpaceLocal(const ANameSpace: string): TStrings;
|
|
|
|
var
|
|
|
|
i : PtrInt;
|
|
|
|
begin
|
|
|
|
i := FNameSpaceList.IndexOf(ANameSpace);
|
|
|
|
if ( i >= 0 ) then
|
|
|
|
Result := FNameSpaceList.Objects[i] as TStrings
|
|
|
|
else
|
|
|
|
Result := nil;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TCustomXsdSchemaParser.GetParentContext() : IParserContext;
|
|
|
|
begin
|
|
|
|
Result := IParserContext(FParentContext);
|
|
|
|
end;
|
|
|
|
|
2013-11-19 11:04:25 +00:00
|
|
|
function TCustomXsdSchemaParser.HasParentContext() : Boolean;
|
|
|
|
begin
|
|
|
|
Result := (FParentContext <> nil);
|
|
|
|
end;
|
|
|
|
|
2007-09-09 22:30:50 +00:00
|
|
|
function TCustomXsdSchemaParser.GetSymbolTable() : TwstPasTreeContainer;
|
|
|
|
begin
|
|
|
|
Result := FSymbols;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TCustomXsdSchemaParser.GetTargetModule() : TPasModule;
|
|
|
|
begin
|
2011-08-29 02:59:57 +00:00
|
|
|
Prepare(True);
|
2007-09-09 22:30:50 +00:00
|
|
|
Result := FModule;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TCustomXsdSchemaParser.GetTargetNameSpace() : string;
|
|
|
|
begin
|
2011-08-29 02:59:57 +00:00
|
|
|
Prepare(True);
|
2007-09-09 22:30:50 +00:00
|
|
|
Result := FTargetNameSpace;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TCustomXsdSchemaParser.GetXsShortNames() : TStrings;
|
|
|
|
begin
|
|
|
|
Result := FXSShortNames;
|
|
|
|
end;
|
|
|
|
|
2009-09-02 12:24:19 +00:00
|
|
|
function TCustomXsdSchemaParser.ParseType(const AName, ATypeKind : string): TPasType;
|
|
|
|
begin
|
|
|
|
Result := InternalParseType(AName,nil);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TCustomXsdSchemaParser.ParseType(
|
|
|
|
const AName : string;
|
|
|
|
const ATypeNode : TDOMNode
|
|
|
|
) : TPasType;
|
|
|
|
begin
|
|
|
|
Result := InternalParseType(AName,ATypeNode);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TCustomXsdSchemaParser.InternalParseType(
|
|
|
|
const AName : string;
|
|
|
|
const ATypeNode : TDOMNode
|
|
|
|
): TPasType;
|
2007-09-09 22:30:50 +00:00
|
|
|
var
|
|
|
|
crsSchemaChild : IObjectCursor;
|
|
|
|
typNd : TDOMNode;
|
|
|
|
typName : string;
|
|
|
|
embededType : Boolean;
|
|
|
|
localTypeName : string;
|
|
|
|
|
|
|
|
procedure Init();
|
|
|
|
begin
|
|
|
|
crsSchemaChild := FChildCursor.Clone() as IObjectCursor;
|
|
|
|
end;
|
|
|
|
|
2009-04-07 16:28:22 +00:00
|
|
|
function ExtractTypeHint(AElement: TDOMNode): string;
|
|
|
|
begin
|
|
|
|
if not wst_findCustomAttributeXsd(FXSShortNames,AElement,s_WST_typeHint,Result) then
|
|
|
|
Result := '';
|
|
|
|
end;
|
|
|
|
|
2007-09-09 22:30:50 +00:00
|
|
|
function FindTypeNode(out ASimpleTypeAlias : TPasType) : Boolean;
|
|
|
|
var
|
|
|
|
nd, oldTypeNode : TDOMNode;
|
|
|
|
crs : IObjectCursor;
|
2009-04-07 16:28:22 +00:00
|
|
|
locStrFilter, locTypeHint : string;
|
|
|
|
locHintedType : TPasType;
|
2007-09-09 22:30:50 +00:00
|
|
|
begin
|
|
|
|
ASimpleTypeAlias := nil;
|
|
|
|
Result := True;
|
2009-09-02 12:24:19 +00:00
|
|
|
if ( ATypeNode <> nil ) then
|
|
|
|
typNd := ATypeNode
|
|
|
|
else
|
|
|
|
typNd := FindNamedNode(crsSchemaChild,localTypeName);
|
2007-09-09 22:30:50 +00:00
|
|
|
if not Assigned(typNd) then
|
2010-10-16 18:38:07 +00:00
|
|
|
raise EXsdTypeNotFoundException.CreateFmt(SERR_TypeDefinitionNotFound,['1',AName]);
|
2013-03-05 15:48:26 +00:00
|
|
|
if AnsiSameText(ExtractNameFromQName(typNd.NodeName),s_element) or
|
|
|
|
AnsiSameText(ExtractNameFromQName(typNd.NodeName),s_attribute)
|
|
|
|
then begin
|
2007-09-09 22:30:50 +00:00
|
|
|
crs := CreateCursorOn(CreateAttributesCursor(typNd,cetRttiNode),ParseFilter(Format('%s = %s',[s_NODE_NAME,QuotedStr(s_type)]),TDOMNodeRttiExposer));
|
|
|
|
crs.Reset();
|
|
|
|
if crs.MoveNext() then begin
|
|
|
|
nd := (crs.GetCurrent() as TDOMNodeRttiExposer).InnerObject;
|
|
|
|
ASimpleTypeAlias := FindElement(ExtractNameFromQName(nd.NodeValue)) as TPasType;
|
|
|
|
if Assigned(ASimpleTypeAlias) then begin
|
2009-04-07 16:28:22 +00:00
|
|
|
if ASimpleTypeAlias.InheritsFrom(TPasNativeSimpleType) then begin
|
|
|
|
locTypeHint := ExtractTypeHint(typNd);
|
|
|
|
if not IsStrEmpty(locTypeHint) then begin
|
2011-09-16 00:56:48 +00:00
|
|
|
locHintedType := FindElement(locTypeHint,[elkName]) as TPasType;
|
2009-04-07 16:28:22 +00:00
|
|
|
if ( locHintedType <> nil ) then
|
|
|
|
ASimpleTypeAlias := locHintedType;
|
|
|
|
end;
|
|
|
|
end;
|
2007-09-09 22:30:50 +00:00
|
|
|
Result := False;
|
|
|
|
end else begin
|
|
|
|
oldTypeNode := typNd;
|
|
|
|
typNd := FindNamedNode(crsSchemaChild,ExtractNameFromQName(nd.NodeValue));
|
|
|
|
if not Assigned(typNd) then
|
2010-10-16 18:38:07 +00:00
|
|
|
raise EXsdTypeNotFoundException.CreateFmt(SERR_TypeDefinitionNotFound,['2',AName]);
|
2007-09-09 22:30:50 +00:00
|
|
|
embededType := False;
|
|
|
|
if ( typNd = oldTypeNode ) then begin
|
|
|
|
typNd := FindNamedNode(crsSchemaChild,ExtractNameFromQName(nd.NodeValue),2);
|
|
|
|
if not Assigned(typNd) then
|
2010-10-16 18:38:07 +00:00
|
|
|
raise EXsdTypeNotFoundException.CreateFmt(SERR_TypeDefinitionNotFound,['2.1',AName]);
|
2007-09-09 22:30:50 +00:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end else begin
|
|
|
|
//locStrFilter := Format('%s = %s or %s = %s ',[s_NODE_NAME,QuotedStr(s_complexType),s_NODE_NAME,QuotedStr(s_simpleType)]);
|
|
|
|
locStrFilter := CreateQualifiedNameFilterStr(s_complexType,FXSShortNames) + ' or ' +
|
|
|
|
CreateQualifiedNameFilterStr(s_simpleType,FXSShortNames);
|
|
|
|
crs := CreateCursorOn(CreateChildrenCursor(typNd,cetRttiNode),ParseFilter(locStrFilter,TDOMNodeRttiExposer));
|
|
|
|
crs.Reset();
|
|
|
|
if not crs.MoveNext() then begin
|
2010-10-16 18:38:07 +00:00
|
|
|
raise EXsdTypeNotFoundException.CreateFmt(SERR_TypeDefinitionNotFound,['3',AName]);
|
2007-09-09 22:30:50 +00:00
|
|
|
end;
|
|
|
|
typNd := (crs.GetCurrent() as TDOMNodeRttiExposer).InnerObject;
|
|
|
|
typName := ExtractNameFromQName(AName);
|
|
|
|
embededType := True;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function ParseComplexType():TPasType;
|
|
|
|
var
|
|
|
|
locParser : TComplexTypeParser;
|
|
|
|
begin
|
|
|
|
locParser := TComplexTypeParser.Create(Self,typNd,typName,embededType);
|
|
|
|
try
|
|
|
|
Result := locParser.Parse();
|
|
|
|
finally
|
|
|
|
FreeAndNil(locParser);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function ParseSimpleType():TPasType;
|
|
|
|
var
|
|
|
|
locParser : TSimpleTypeParser;
|
|
|
|
begin
|
|
|
|
locParser := TSimpleTypeParser.Create(Self,typNd,typName,embededType);
|
|
|
|
try
|
|
|
|
Result := locParser.Parse();
|
|
|
|
finally
|
|
|
|
FreeAndNil(locParser);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function CreateTypeAlias(const ABase : TPasType): TPasType;
|
|
|
|
var
|
2013-11-19 11:04:25 +00:00
|
|
|
hasInterName : Boolean;
|
|
|
|
baseName,internalName : string;
|
2007-09-09 22:30:50 +00:00
|
|
|
begin
|
2013-11-19 11:04:25 +00:00
|
|
|
baseName := ExtractNameFromQName(AName);
|
|
|
|
internalName := ExtractIdentifier(baseName);
|
|
|
|
hasInterName := IsReservedKeyWord(internalName) or
|
|
|
|
( not IsValidIdent(internalName) );
|
|
|
|
if hasInterName then begin
|
|
|
|
internalName := '_' + internalName;
|
2007-09-09 22:30:50 +00:00
|
|
|
end;
|
2013-11-19 11:04:25 +00:00
|
|
|
Result := TPasType(SymbolTable.CreateElement(TPasAliasType,internalName,SymbolTable.CurrentModule.InterfaceSection,visDefault,'',0));
|
|
|
|
SymbolTable.RegisterExternalAlias(Result,baseName);
|
2007-09-09 22:30:50 +00:00
|
|
|
TPasAliasType(Result).DestType := ABase;
|
|
|
|
ABase.AddRef();
|
|
|
|
end;
|
|
|
|
|
|
|
|
function CreateUnresolveType(): TPasType;
|
|
|
|
var
|
|
|
|
hasInternameName : Boolean;
|
2013-11-19 11:04:25 +00:00
|
|
|
internameName, baseName : string;
|
2007-09-09 22:30:50 +00:00
|
|
|
begin
|
2013-11-19 11:04:25 +00:00
|
|
|
baseName := ExtractNameFromQName(AName);
|
|
|
|
internameName := ExtractIdentifier(baseName);
|
|
|
|
hasInternameName := IsReservedKeyWord(baseName) or
|
|
|
|
(not IsValidIdent(internameName));
|
2007-09-09 22:30:50 +00:00
|
|
|
if hasInternameName then begin
|
|
|
|
internameName := '_' + internameName;
|
|
|
|
end;
|
|
|
|
Result := TPasUnresolvedTypeRef(SymbolTable.CreateElement(TPasUnresolvedTypeRef,internameName,SymbolTable.CurrentModule.InterfaceSection,visDefault,'',0));
|
2013-11-19 11:04:25 +00:00
|
|
|
if not AnsiSameText(internameName,baseName) then
|
|
|
|
SymbolTable.RegisterExternalAlias(Result,baseName);
|
2007-09-09 22:30:50 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
var
|
|
|
|
frwType, aliasType : TPasType;
|
|
|
|
sct : TPasSection;
|
|
|
|
shortNameSpace, longNameSpace : string;
|
|
|
|
typeModule : TPasModule;
|
2009-09-02 12:24:19 +00:00
|
|
|
locTypeNodeFound : Boolean;
|
2007-09-09 22:30:50 +00:00
|
|
|
begin
|
2011-08-29 02:59:57 +00:00
|
|
|
Prepare(True);
|
2009-11-23 17:55:10 +00:00
|
|
|
if not FImportParsed then
|
|
|
|
ParseImportDocuments();
|
2011-08-29 02:59:57 +00:00
|
|
|
if not FIncludeParsed then
|
|
|
|
ParseIncludeDocuments();
|
2008-06-06 14:49:11 +00:00
|
|
|
sct := nil;
|
2010-10-16 18:38:07 +00:00
|
|
|
DoOnMessage(mtInfo, Format(SERR_Parsing,[AName]));
|
2007-09-09 22:30:50 +00:00
|
|
|
try
|
|
|
|
embededType := False;
|
|
|
|
aliasType := nil;
|
|
|
|
ExplodeQName(AName,localTypeName,shortNameSpace);
|
|
|
|
if IsStrEmpty(shortNameSpace) then begin
|
|
|
|
typeModule := FModule;
|
|
|
|
end else begin
|
|
|
|
if not FindNameSpace(shortNameSpace,longNameSpace) then
|
2010-10-16 18:38:07 +00:00
|
|
|
raise EXsdParserAssertException.CreateFmt(SERR_UnableToResolveNamespace,[shortNameSpace]);
|
2007-09-09 22:30:50 +00:00
|
|
|
typeModule := SymbolTable.FindModule(longNameSpace);
|
|
|
|
end;
|
|
|
|
if ( typeModule = nil ) then
|
|
|
|
raise EXsdTypeNotFoundException.Create(AName);
|
|
|
|
Result := SymbolTable.FindElementInModule(localTypeName,typeModule) as TPasType;
|
2010-10-11 12:28:07 +00:00
|
|
|
if (Result <> nil) and (not Result.InheritsFrom(TPasUnresolvedTypeRef)) then
|
|
|
|
Exit;
|
2009-09-02 12:24:19 +00:00
|
|
|
Init();
|
|
|
|
locTypeNodeFound := FindTypeNode(aliasType);
|
|
|
|
if ( Result <> nil ) and ( typeModule = FModule ) and
|
|
|
|
( not Result.InheritsFrom(TPasUnresolvedTypeRef) )
|
|
|
|
then begin
|
|
|
|
if locTypeNodeFound and ( embededType <> ( SymbolTable.Properties.GetValue(Result,sEMBEDDED_TYPE) = '1' ) ) then
|
|
|
|
Result := nil;
|
|
|
|
end;
|
2007-09-09 22:30:50 +00:00
|
|
|
if ( ( Result = nil ) or Result.InheritsFrom(TPasUnresolvedTypeRef) ) and
|
|
|
|
( typeModule = FModule )
|
|
|
|
then begin
|
|
|
|
sct := FModule.InterfaceSection;
|
|
|
|
frwType := Result;
|
|
|
|
Result := nil;
|
|
|
|
Init();
|
2009-09-02 12:24:19 +00:00
|
|
|
if locTypeNodeFound {FindTypeNode(aliasType)} then begin
|
2007-09-09 22:30:50 +00:00
|
|
|
if AnsiSameText(ExtractNameFromQName(typNd.NodeName),s_complexType) then begin
|
|
|
|
Result := ParseComplexType();
|
|
|
|
end else if AnsiSameText(ExtractNameFromQName(typNd.NodeName),s_simpleType) then begin
|
|
|
|
Result := ParseSimpleType();
|
|
|
|
end;
|
|
|
|
if Assigned(Result) then begin
|
|
|
|
if Assigned(frwType) and AnsiSameText(SymbolTable.GetExternalName(Result),SymbolTable.GetExternalName(frwType)) then begin
|
|
|
|
Result.Name := frwType.Name;
|
|
|
|
SymbolTable.RegisterExternalAlias(Result,SymbolTable.GetExternalName(frwType));
|
|
|
|
end;
|
|
|
|
end else begin
|
2010-10-16 18:38:07 +00:00
|
|
|
raise EXsdTypeNotFoundException.CreateFmt(SERR_TypeNodeFoundButUnableToParseIt,[AName]);
|
2007-09-09 22:30:50 +00:00
|
|
|
end;
|
|
|
|
end else begin
|
|
|
|
Result := CreateTypeAlias(aliasType);
|
|
|
|
end;
|
|
|
|
if ( frwType <> nil ) then begin
|
|
|
|
sct.Declarations.Extract(frwType);
|
|
|
|
sct.Types.Extract(frwType);
|
|
|
|
frwType.Release();
|
|
|
|
end;
|
|
|
|
sct.Declarations.Add(Result);
|
|
|
|
sct.Types.Add(Result);
|
|
|
|
if Result.InheritsFrom(TPasClassType) then begin
|
|
|
|
sct.Classes.Add(Result);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
except
|
|
|
|
on e : EXsdTypeNotFoundException do begin
|
|
|
|
Result := CreateUnresolveType();
|
2008-06-06 14:49:11 +00:00
|
|
|
if ( sct = nil ) then
|
|
|
|
sct := FModule.InterfaceSection;
|
2007-09-09 22:30:50 +00:00
|
|
|
sct.Declarations.Add(Result);
|
|
|
|
sct.Types.Add(Result);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2010-10-11 12:28:07 +00:00
|
|
|
procedure TCustomXsdSchemaParser.CreateImportParsers();
|
|
|
|
var
|
2010-11-08 14:26:03 +00:00
|
|
|
crsSchemaChild : IObjectCursor;
|
2010-10-11 12:28:07 +00:00
|
|
|
strFilter, locFileName, locNameSpace : string;
|
|
|
|
importNode : TDOMElement;
|
|
|
|
importDoc : TXMLDocument;
|
|
|
|
locParser : IXsdPaser;
|
|
|
|
locOldCurrentModule : TPasModule;
|
|
|
|
locContinue : Boolean;
|
2011-08-29 02:59:57 +00:00
|
|
|
locLocator, loctempLocator : IDocumentLocator;
|
|
|
|
locContext : IParserContext;
|
2011-11-26 17:54:55 +00:00
|
|
|
locUsesList : TList2;
|
2011-08-29 02:59:57 +00:00
|
|
|
locModule : TPasModule;
|
|
|
|
locName, s : string;
|
|
|
|
i : Integer;
|
2010-10-11 12:28:07 +00:00
|
|
|
begin
|
|
|
|
if FImportParsed then
|
|
|
|
Exit;
|
2011-08-29 02:59:57 +00:00
|
|
|
Prepare(True);
|
2010-10-11 12:28:07 +00:00
|
|
|
locLocator := GetDocumentLocator();
|
|
|
|
if (locLocator = nil) then
|
|
|
|
Exit;
|
|
|
|
|
|
|
|
if Assigned(FChildCursor) then begin
|
|
|
|
locOldCurrentModule := SymbolTable.CurrentModule;
|
|
|
|
try
|
2011-08-29 02:59:57 +00:00
|
|
|
locUsesList := FModule.InterfaceSection.UsesList;
|
2010-10-11 12:28:07 +00:00
|
|
|
crsSchemaChild := FChildCursor.Clone() as IObjectCursor;
|
|
|
|
strFilter := CreateQualifiedNameFilterStr(s_import,FXSShortNames);
|
|
|
|
crsSchemaChild := CreateCursorOn(crsSchemaChild,ParseFilter(strFilter,TDOMNodeRttiExposer));
|
|
|
|
crsSchemaChild.Reset();
|
|
|
|
while crsSchemaChild.MoveNext() do begin
|
|
|
|
importNode := (crsSchemaChild.GetCurrent() as TDOMNodeRttiExposer).InnerObject as TDOMElement;
|
|
|
|
if ( importNode.Attributes <> nil ) and ( importNode.Attributes.Length > 0 ) then begin
|
|
|
|
locFileName := NodeValue(importNode.Attributes.GetNamedItem(s_schemaLocation));
|
2011-08-29 02:59:57 +00:00
|
|
|
if not IsStrEmpty(locFileName) then begin
|
|
|
|
if locLocator.Find(locFileName,importDoc) then begin
|
|
|
|
locNameSpace := NodeValue(importNode.Attributes.GetNamedItem(s_namespace));
|
|
|
|
locContinue := IsStrEmpty(locNameSpace) or (FXsdParsers = nil) or (FXsdParsers.IndexOf(locNameSpace) = -1);//( SymbolTable.FindModule(locNameSpace) = nil );
|
|
|
|
if locContinue then begin
|
|
|
|
if (FXsdParsers = nil) then begin
|
|
|
|
FXsdParsers := TStringList.Create();
|
|
|
|
FXsdParsers.Duplicates := dupIgnore;
|
|
|
|
FXsdParsers.Sorted := True;
|
|
|
|
end;
|
|
|
|
locParser := TCustomXsdSchemaParserClass(Self.ClassType).Create(
|
|
|
|
importDoc,
|
|
|
|
importDoc.DocumentElement,
|
|
|
|
SymbolTable,
|
|
|
|
Self as IParserContext
|
|
|
|
);
|
|
|
|
locContext := locParser as IParserContext;
|
|
|
|
loctempLocator := locLocator.Clone();
|
|
|
|
loctempLocator.SetBasePath(locLocator.FindPath(locFileName));
|
|
|
|
locContext.SetDocumentLocator(loctempLocator);
|
|
|
|
FXsdParsers.AddObject(locNameSpace,TIntfObjectRef.Create(locParser));
|
|
|
|
locParser.SetNotifier(FOnMessage);
|
|
|
|
//locParser.ParseTypes();
|
|
|
|
locModule := locContext.GetTargetModule();
|
|
|
|
if (locModule <> FModule) and (locUsesList.IndexOf(locModule) = -1) then begin
|
2013-11-19 11:04:25 +00:00
|
|
|
s := ChangeFileExt(ExtractFileName(locFileName),'');
|
|
|
|
s := ExtractIdentifier(s);
|
2011-08-29 02:59:57 +00:00
|
|
|
i := 1;
|
|
|
|
locName := s;
|
|
|
|
while (FSymbols.FindModule(locName) <> nil) do begin
|
|
|
|
locName := Format('%s%d',[s,i]);
|
|
|
|
Inc(i);
|
|
|
|
end;
|
|
|
|
locModule.Name := locName;
|
|
|
|
locModule.AddRef();
|
|
|
|
locUsesList.Add(locModule);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end else begin
|
|
|
|
DoOnMessage(mtError,Format(SERR_FileNotFound,[locFileName]));
|
2010-10-11 12:28:07 +00:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
finally
|
|
|
|
SymbolTable.SetCurrentModule(locOldCurrentModule);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2007-09-09 22:30:50 +00:00
|
|
|
procedure TCustomXsdSchemaParser.ParseTypes();
|
|
|
|
var
|
2007-10-19 15:30:20 +00:00
|
|
|
crsSchemaChild, typTmpCrs : IObjectCursor;
|
2007-09-09 22:30:50 +00:00
|
|
|
typFilterStr : string;
|
|
|
|
typNode : TDOMNode;
|
|
|
|
begin
|
2011-08-29 02:59:57 +00:00
|
|
|
Prepare(True);
|
2013-11-19 11:04:25 +00:00
|
|
|
ParseImportDocuments();
|
2011-08-29 02:59:57 +00:00
|
|
|
ParseIncludeDocuments();
|
2007-09-09 22:30:50 +00:00
|
|
|
if Assigned(FChildCursor) then begin
|
|
|
|
crsSchemaChild := FChildCursor.Clone() as IObjectCursor;
|
|
|
|
typFilterStr := Format(
|
2013-03-05 15:48:26 +00:00
|
|
|
'%s or %s or %s or %s',
|
2007-09-09 22:30:50 +00:00
|
|
|
[ CreateQualifiedNameFilterStr(s_complexType,FXSShortNames),
|
|
|
|
CreateQualifiedNameFilterStr(s_simpleType,FXSShortNames),
|
2013-03-05 15:48:26 +00:00
|
|
|
CreateQualifiedNameFilterStr(s_element,FXSShortNames),
|
|
|
|
CreateQualifiedNameFilterStr(s_attribute,FXSShortNames)
|
2007-09-09 22:30:50 +00:00
|
|
|
]
|
|
|
|
);
|
|
|
|
crsSchemaChild := CreateCursorOn(crsSchemaChild,ParseFilter(typFilterStr,TDOMNodeRttiExposer));
|
|
|
|
crsSchemaChild.Reset();
|
|
|
|
while crsSchemaChild.MoveNext() do begin
|
|
|
|
typNode := (crsSchemaChild.GetCurrent() as TDOMNodeRttiExposer).InnerObject;
|
|
|
|
typTmpCrs := CreateAttributesCursor(typNode,cetRttiNode);
|
|
|
|
if Assigned(typTmpCrs) then begin
|
|
|
|
typTmpCrs.Reset();
|
|
|
|
typTmpCrs := CreateCursorOn(typTmpCrs,ParseFilter(Format('%s=%s',[s_NODE_NAME,QuotedStr(s_name)]),TDOMNodeRttiExposer));
|
|
|
|
typTmpCrs.Reset();
|
|
|
|
if typTmpCrs.MoveNext() then begin
|
2009-09-02 12:24:19 +00:00
|
|
|
InternalParseType(
|
|
|
|
(typTmpCrs.GetCurrent() as TDOMNodeRttiExposer).NodeValue,
|
|
|
|
typNode
|
2007-09-09 22:30:50 +00:00
|
|
|
);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
2013-11-19 11:04:25 +00:00
|
|
|
if (FCheckedTypes <> nil) and (FCheckedTypes.Count > 0) then
|
|
|
|
CheckDuplicatedProperties(FCheckedTypes,FSymbols);
|
2007-09-09 22:30:50 +00:00
|
|
|
end;
|
|
|
|
|
2011-08-29 02:59:57 +00:00
|
|
|
procedure TCustomXsdSchemaParser.Prepare(const AMustSucceed : Boolean);
|
2007-09-09 22:30:50 +00:00
|
|
|
var
|
|
|
|
locAttCursor : IObjectCursor;
|
|
|
|
prntCtx : IParserContext;
|
|
|
|
nd : TDOMNode;
|
|
|
|
i : PtrInt;
|
|
|
|
ls : TStrings;
|
2011-08-29 02:59:57 +00:00
|
|
|
ok : Boolean;
|
2007-09-09 22:30:50 +00:00
|
|
|
begin
|
2011-08-29 02:59:57 +00:00
|
|
|
if FPrepared then
|
|
|
|
exit;
|
|
|
|
|
|
|
|
FTargetNameSpace := '';
|
|
|
|
ok := False;
|
|
|
|
if (FSchemaNode.Attributes <> nil) and (GetNodeListCount(FSchemaNode.Attributes) > 0) then begin
|
|
|
|
nd := FSchemaNode.Attributes.GetNamedItem(s_targetNamespace);
|
|
|
|
if (nd <> nil) then begin
|
|
|
|
FTargetNameSpace := nd.NodeValue;
|
|
|
|
ok := True;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
prntCtx := GetParentContext();
|
|
|
|
if not ok then begin
|
|
|
|
if (poParsingIncludeSchema in FSimpleOptions) and (prntCtx <> nil) then begin
|
|
|
|
FTargetNameSpace := prntCtx.GetTargetNameSpace();
|
|
|
|
ok := True;
|
|
|
|
end else begin
|
|
|
|
if not AMustSucceed then
|
|
|
|
exit;
|
|
|
|
raise EXsdParserAssertException.CreateFmt(SERR_SchemaNodeRequiredAttribute,[s_targetNamespace]);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
FPrepared := True;
|
2007-09-09 22:30:50 +00:00
|
|
|
if IsStrEmpty(FModuleName) then
|
|
|
|
FModuleName := ExtractIdentifier(FTargetNameSpace);
|
|
|
|
if ( SymbolTable.FindModule(s_xs) = nil ) then begin
|
|
|
|
CreateWstInterfaceSymbolTable(SymbolTable);
|
|
|
|
end;
|
|
|
|
FChildCursor := CreateChildrenCursor(FSchemaNode,cetRttiNode);
|
|
|
|
|
|
|
|
locAttCursor := CreateAttributesCursor(FSchemaNode,cetRttiNode);
|
|
|
|
BuildNameSpaceList(locAttCursor,FNameSpaceList);
|
|
|
|
FXSShortNames := FindShortNamesForNameSpaceLocal(s_xs);
|
|
|
|
if ( FXSShortNames = nil ) then begin
|
|
|
|
if ( prntCtx = nil ) then
|
2010-10-16 18:38:07 +00:00
|
|
|
raise EXsdParserAssertException.CreateFmt(SERR_InvalidSchemaDoc_NamespaceNotFound,[s_xs]);
|
2007-09-09 22:30:50 +00:00
|
|
|
FXSShortNames := prntCtx.FindShortNamesForNameSpace(s_xs);
|
|
|
|
if ( FXSShortNames = nil ) then
|
2010-10-16 18:38:07 +00:00
|
|
|
raise EXsdParserAssertException.CreateFmt(SERR_InvalidSchemaDoc_NamespaceNotFoundShort,[s_xs]);
|
2007-09-09 22:30:50 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
if Assigned(prntCtx) then begin
|
|
|
|
for i:= 0 to Pred(FNameSpaceList.Count) do begin
|
|
|
|
ls := prntCtx.FindShortNamesForNameSpace(FNameSpaceList[i]);
|
|
|
|
if Assigned(ls) then
|
|
|
|
(FNameSpaceList.Objects[i] as TStrings).AddStrings(ls);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
FModule := SymbolTable.FindModule(FTargetNameSpace);
|
|
|
|
if ( FModule = nil ) then begin
|
|
|
|
FModule := TPasModule(SymbolTable.CreateElement(TPasModule,FModuleName,SymbolTable.Package,visDefault,'',0));
|
|
|
|
SymbolTable.Package.Modules.Add(FModule);
|
|
|
|
SymbolTable.RegisterExternalAlias(FModule,FTargetNameSpace);
|
2010-02-27 16:17:21 +00:00
|
|
|
FModule.InterfaceSection := TInterfaceSection(SymbolTable.CreateElement(TInterfaceSection,'',FModule,visDefault,'',0));
|
2007-09-09 22:30:50 +00:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ TXsdParser }
|
|
|
|
|
|
|
|
constructor TXsdParser.Create(
|
|
|
|
ADoc : TXMLDocument;
|
|
|
|
ASymbols : TwstPasTreeContainer;
|
2008-09-10 01:46:45 +00:00
|
|
|
const AModuleName : string;
|
|
|
|
const ANotifier : TOnParserMessage
|
2007-09-09 22:30:50 +00:00
|
|
|
);
|
|
|
|
var
|
|
|
|
locName : string;
|
|
|
|
begin
|
|
|
|
inherited Create(ADoc,ADoc.DocumentElement,ASymbols,nil);
|
2008-09-10 01:46:45 +00:00
|
|
|
if Assigned(ANotifier) then
|
|
|
|
FOnMessage := ANotifier;
|
2007-09-09 22:30:50 +00:00
|
|
|
if not IsStrEmpty(AModuleName) then begin
|
|
|
|
locName := ExtractIdentifier(AModuleName);
|
|
|
|
if not IsStrEmpty(locName) then begin
|
|
|
|
FModuleName := locName;
|
2011-09-10 22:29:42 +00:00
|
|
|
if (Module <> nil) then
|
|
|
|
Module.Name := FModuleName;
|
2007-09-09 22:30:50 +00:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
end.
|