From fd9c3093098403d7631d639246d18dc2ceba78db Mon Sep 17 00:00:00 2001 From: Mark van Renswoude Date: Wed, 14 May 2008 13:30:54 +0000 Subject: [PATCH] Changed: hints file now uses XPath expressions --- Forms/MainFrm.dfm | Bin 3024 -> 3022 bytes Forms/MainFrm.pas | 339 ++++++++++++++++++++++++------ Units/DataBindingHintsXML.pas | 193 ++++++++++++++--- Units/XMLDataBindingGenerator.pas | 78 ++++--- XSD/DataBindingHints.xsd | 24 ++- 5 files changed, 516 insertions(+), 118 deletions(-) diff --git a/Forms/MainFrm.dfm b/Forms/MainFrm.dfm index ec6dbfc1257be3f0b02fe103630625a3d598db94..a1e1733abd9e900f263c3c789c395087c565c8a9 100644 GIT binary patch delta 38 ucmca0eokEAKNmxYucN1*n}3imgMq;AjRMnH*x8B;+%j`gH?L<=WCsB6s0-%+ delta 40 wcmX>nenDK|KNmxYucN1*n}3imgMq-_jRMnHI5~<7-12i$Qj0dPWl>}Y019FZ#{d8T diff --git a/Forms/MainFrm.pas b/Forms/MainFrm.pas index 17a0394..2edf967 100644 --- a/Forms/MainFrm.pas +++ b/Forms/MainFrm.pas @@ -62,12 +62,9 @@ type procedure feSchemaPropertiesChange(Sender: TObject); procedure btnHintsClick(Sender: TObject); private - FHints: IXMLDataBindingHints; - FHintsXPath: IDOMNodeSelect; - function CheckValidSchemaFile(): Boolean; + function CheckReadOnly(const AFileName: String): Boolean; - procedure PostProcessItem(Sender: TObject; Item: TXMLDataBindingItem); procedure GetFileName(Sender: TObject; const SchemaName: String; var Path, FileName: String); function GetSettingsFileName(const AFileName: String): String; @@ -91,15 +88,26 @@ uses DelphiXMLDataBindingGenerator; -const - XPathHintBase = '/d:DataBindingHints'; +type + TProtectedXMLDataBindingItem = class(TXMLDataBindingItem); - XPathHintEnumerationMember = XPathHintBase + '/d:Enumerations' + - '/d:Enumeration[@Name=''%:s'']' + - '/d:Member[@Name=''%:s'']/text()'; + THintsDelphiXMLDataBindingGenerator = class(TDelphiXMLDataBindingGenerator) + private + FHints: IXMLDataBindingHints; + protected + procedure GenerateDataBinding; override; - XPathHintDocumentElement = XPathHintBase + '/d:DocumentElements' + - '/d:DocumentElement[@Name=''%:s'']'; + procedure ProcessHints; + + procedure ProcessEnumerations; + procedure ProcessDocumentElements; + procedure ProcessInterfaces; + + function FindSchema(const ASchemaName: String; out ASchema: TXMLDataBindingSchema): Boolean; + function FindNode(const ASchemaName, AXPath: String; out AItem: TXMLDataBindingItem): Boolean; + public + property Hints: IXMLDataBindingHints read FHints write FHints; + end; {$R *.dfm} @@ -142,7 +150,8 @@ end; procedure TMainForm.btnGenerateClick(Sender: TObject); var hintsFile: String; - domDocument: IXMLDOMDocument2; + hints: IXMLDataBindingHints; + generator: THintsDelphiXMLDataBindingGenerator; begin if not CheckValidSchemaFile() then @@ -150,43 +159,37 @@ begin hintsFile := ChangeFileExt(feSchema.Text, '.hints.xml'); if FileExists(hintsFile) then - begin - FHints := LoadDataBindingHints(hintsFile); - - { Set the default namespace for XPath expressions to work } - domDocument := ((FHints.OwnerDocument.DOMDocument as IXMLDOMNodeRef).GetXMLDOMNode as IXMLDOMDocument2); - domDocument.setProperty('SelectionLanguage', 'XPath'); - domDocument.setProperty('SelectionNamespaces', 'xmlns:d="' + DataBindingHintsXML.TargetNamespace + '"'); - - FHintsXPath := (FHints.OwnerDocument.DocumentElement.DOMNode as IDOMNodeSelect); - end; + hints := LoadDataBindingHints(hintsFile); try - with TDelphiXMLDataBindingGenerator.Create() do + generator := THintsDelphiXMLDataBindingGenerator.Create(); try + generator.Hints := hints; + if rbFile.Checked then begin - OutputType := otSingle; - OutputPath := feFile.Text; + if not CheckReadOnly(feFile.Text) then + Exit; + + generator.OutputType := otSingle; + generator.OutputPath := feFile.Text; end else if rbFolder.Checked then begin - OutputType := otMultiple; - OutputPath := deFolder.Text; + generator.OutputType := otMultiple; + generator.OutputPath := deFolder.Text; end; - OnPostProcessItem := PostProcessItem; - OnGetFileName := GetFileName; - Execute(feSchema.Text); + generator.OnGetFileName := GetFileName; + generator.Execute(feSchema.Text); SaveSettings(feSchema.Text); ShowMessage('The data binding has been generated.'); finally - Free(); + FreeAndNil(generator); end; finally - FHints := nil; - FHintsXPath := nil; + hints := nil; end; end; @@ -197,37 +200,6 @@ begin end; -procedure TMainForm.PostProcessItem(Sender: TObject; Item: TXMLDataBindingItem); -var - member: TXMLDataBindingEnumerationMember; - hint: IDOMNode; - -begin - if not Assigned(FHintsXPath) then - Exit; - - if Item.ItemType = itEnumerationMember then - begin - { Check if a hint for a new name is available } - member := TXMLDataBindingEnumerationMember(Item); - hint := FHintsXPath.selectNode(NamedFormat(XPathHintEnumerationMember, - ['Enumeration', member.Enumeration.Name, - 'Member', member.Name])); - - if Assigned(hint) and (Length(hint.nodeValue) > 0) then - Item.TranslatedName := hint.nodeValue; - end; - - if Item.ItemType = itInterface then - begin - if FHints.HasDocumentElements then - Item.DocumentElement := Assigned(FHintsXPath.selectNode(NamedFormat(XPathHintDocumentElement, - ['Name', Item.Name]))); - - end; -end; - - procedure TMainForm.GetFileName(Sender: TObject; const SchemaName: String; var Path, FileName: String); begin FileName := ChangeFileExt(edtFolderPrefix.Text + FileName, @@ -354,6 +326,24 @@ begin 'Schema file does not exist', MB_OK or MB_ICONERROR); ActiveControl := feFile; + Exit; + end; +end; + + +function TMainForm.CheckReadOnly(const AFileName: String): Boolean; +begin + Result := True; + + if FileExists(AFileName) and FileIsReadOnly(AFileName) then + begin + if MessageBox(Self.Handle, 'The output file is read-only. Do you want to ' + + 'remove the read-only attribute?', + 'Read-only', MB_YESNO or MB_ICONQUESTION) = ID_YES then + begin + Result := FileSetReadOnly(AFileName, False); + end else + Result := False; end; end; @@ -380,6 +370,227 @@ begin end; end; + +{ THintsDelphiXMLDataBindingGenerator } +procedure THintsDelphiXMLDataBindingGenerator.GenerateDataBinding; +begin + if Assigned(Hints) then + ProcessHints; + + inherited GenerateDataBinding; +end; + + +procedure THintsDelphiXMLDataBindingGenerator.ProcessHints; +begin + if Hints.HasEnumerations then + ProcessEnumerations; + + if Hints.HasDocumentElements then + ProcessDocumentElements; + + if Hints.HasInterfaces then + ProcessInterfaces; +end; + + +procedure THintsDelphiXMLDataBindingGenerator.ProcessEnumerations; +var + itemIndex: Integer; + enumeration: IXMLEnumeration; + schemaItem: TXMLDataBindingItem; + enumerationItem: TXMLDataBindingEnumeration; + hintMemberIndex: Integer; + memberName: String; + memberIndex: Integer; + +begin + for itemIndex := 0 to Pred(Hints.Enumerations.Count) do + begin + enumeration := Hints.Enumerations[itemIndex]; + + if FindNode(enumeration.Schema, enumeration.XPath, schemaItem) and + (schemaItem.ItemType = itEnumeration) then + begin + enumerationItem := TXMLDataBindingEnumeration(schemaItem); + + for hintMemberIndex := 0 to Pred(enumeration.Count) do + begin + memberName := enumeration.Member[hintMemberIndex].Name; + + for memberIndex := 0 to Pred(enumerationItem.MemberCount) do + begin + if enumerationItem.Members[memberIndex].Name = memberName then + begin + enumerationItem.Members[memberIndex].TranslatedName := enumeration[hintMemberIndex].Text; + Break; + end; + end; + end; + end; + end; +end; + + +procedure THintsDelphiXMLDataBindingGenerator.ProcessDocumentElements; +var + schemaIndex: Integer; + schema: TXMLDataBindingSchema; + itemIndex: Integer; + documentElement: IXMLDocumentElement; + schemaItem: TXMLDataBindingItem; + +begin + for schemaIndex := 0 to Pred(SchemaCount) do + begin + schema := Schemas[schemaIndex]; + + for itemIndex := 0 to Pred(schema.ItemCount) do + schema.Items[itemIndex].DocumentElement := False; + end; + + for itemIndex := 0 to Pred(Hints.DocumentElements.Count) do + begin + documentElement := Hints.DocumentElements[itemIndex]; + + if FindNode(documentElement.Schema, documentElement.XPath, schemaItem) then + begin + if schemaItem.ItemType = itInterface then + schemaItem.DocumentElement := True; + end; + end; +end; + + +procedure THintsDelphiXMLDataBindingGenerator.ProcessInterfaces; +var + itemIndex: Integer; + interfaceName: IXMLInterfaceName; + schemaItem: TXMLDataBindingItem; + +begin + for itemIndex := 0 to Pred(Hints.Interfaces.Count) do + begin + interfaceName := Hints.Interfaces[itemIndex]; + + if FindNode(interfaceName.Schema, interfaceName.XPath, schemaItem) then + begin + if schemaItem.ItemType in [itInterface, itEnumeration] then + schemaItem.TranslatedName := interfaceName.Text; + end; + end; +end; + + +function THintsDelphiXMLDataBindingGenerator.FindSchema(const ASchemaName: String; out ASchema: TXMLDataBindingSchema): Boolean; +var + schemaIndex: Integer; + +begin + Result := False; + + if SchemaCount > 0 then + begin + if Length(ASchemaName) = 0 then + begin + ASchema := Schemas[0]; + Result := True; + end else + begin + for schemaIndex := 0 to Pred(SchemaCount) do + if SameText(Schemas[schemaIndex].SchemaName, ASchemaName) then + begin + ASchema := Schemas[schemaIndex]; + Result := True; + Break; + end; + end; + end; +end; + + +function THintsDelphiXMLDataBindingGenerator.FindNode(const ASchemaName, AXPath: String; out AItem: TXMLDataBindingItem): Boolean; + + function SameNode(ANode1, ANode2: IDOMNode): Boolean; + var + attributeIndex: Integer; + attribute1: IDOMNode; + attribute2: IDOMNode; + hasParent1: Boolean; + hasParent2: Boolean; + + begin + { Compare name and number of attributes } + Result := (ANode1.nodeName = ANode2.nodeName) and + (ANode1.attributes.length = ANode2.attributes.length); + + if Result then + begin + { Compare attribute content } + for attributeIndex := 0 to Pred(ANode1.attributes.length) do + begin + attribute1 := ANode1.attributes[attributeIndex]; + attribute2 := ANode2.attributes[attributeIndex]; + + Result := (attribute1.nodeName = attribute2.nodeName) and + (attribute1.nodeValue = attribute2.nodeValue); + + if not Result then + Break; + end; + + if Result then + begin + { Compare parent nodes } + hasParent1 := Assigned(ANode1.parentNode) and (ANode1.parentNode.nodeType <> NODE_DOCUMENT); + hasParent2 := Assigned(ANode2.parentNode) and (ANode2.parentNode.nodeType <> NODE_DOCUMENT); + + if hasParent1 = hasParent2 then + begin + if hasParent1 then + Result := SameNode(ANode1.parentNode, ANode2.parentNode); + end else + Result := False; + end; + end; + end; + + +var + schema: TXMLDataBindingSchema; + schemaItem: IDOMNode; + item: TProtectedXMLDataBindingItem; + itemIndex: Integer; + domDocument: IXMLDOMDocument2; + +begin + Result := False; + + if (Length(AXPath) > 0) and FindSchema(ASchemaName, schema) then + begin + domDocument := ((schema.SchemaDef.OwnerDocument.DOMDocument as IXMLDOMNodeRef).GetXMLDOMNode as IXMLDOMDocument2); + domDocument.setProperty('SelectionLanguage', 'XPath'); + domDocument.setProperty('SelectionNamespaces', 'xmlns:xs="http://www.w3.org/2001/XMLSchema"'); + + schemaItem := (schema.SchemaDef.DOMNode as IDOMNodeSelect).selectNode(AXPath); + + if Assigned(schemaItem) then + begin + for itemIndex := 0 to Pred(schema.ItemCount) do + begin + item := TProtectedXMLDataBindingItem(schema.Items[itemIndex]); + + if Assigned(item.SchemaItem) and SameNode(item.SchemaItem.DOMNode, schemaItem) then + begin + AItem := schema.Items[itemIndex]; + Result := True; + Break; + end; + end; + end; + end; +end; + end. diff --git a/Units/DataBindingHintsXML.pas b/Units/DataBindingHintsXML.pas index 376de3c..629a468 100644 --- a/Units/DataBindingHintsXML.pas +++ b/Units/DataBindingHintsXML.pas @@ -1,7 +1,7 @@ { X2Software XML Data Binding - Generated on: 25-4-2008 10:37:37 + Generated on: 14-5-2008 11:21:00 Generated from: P:\test\XMLDataBinding\XSD\DataBindingHints.xsd } unit DataBindingHintsXML; @@ -20,26 +20,32 @@ type IXMLMember = interface; IXMLDocumentElements = interface; IXMLDocumentElement = interface; + IXMLInterfaces = interface; + IXMLInterfaceName = interface; { Interfaces for DataBindingHints } { Contains hints and mappings for the data binding output } IXMLDataBindingHints = interface(IXMLNode) - ['{33A3ED30-3F1C-4607-A848-D3F17297687F}'] + ['{D2B7C152-7F8F-4B0F-9270-7330351B8D4E}'] function GetHasEnumerations: Boolean; function GetEnumerations: IXMLEnumerations; function GetHasDocumentElements: Boolean; function GetDocumentElements: IXMLDocumentElements; + function GetHasInterfaces: Boolean; + function GetInterfaces: IXMLInterfaces; property HasEnumerations: Boolean read GetHasEnumerations; property Enumerations: IXMLEnumerations read GetEnumerations; property HasDocumentElements: Boolean read GetHasDocumentElements; property DocumentElements: IXMLDocumentElements read GetDocumentElements; + property HasInterfaces: Boolean read GetHasInterfaces; + property Interfaces: IXMLInterfaces read GetInterfaces; end; IXMLEnumerations = interface(IXMLNodeCollection) - ['{BD382537-6E8E-4821-A6FB-598234A7B646}'] + ['{1D5E90E0-06DD-4476-BA73-0753D35B6193}'] function Get_Enumeration(Index: Integer): IXMLEnumeration; function Add: IXMLEnumeration; function Insert(Index: Integer): IXMLEnumeration; @@ -48,22 +54,25 @@ type end; IXMLEnumeration = interface(IXMLNodeCollection) - ['{DC00C775-25B9-4612-A712-9D2DAC346415}'] + ['{07097378-D346-4809-B0A2-86C4BA09C124}'] function Get_Member(Index: Integer): IXMLMember; function Add: IXMLMember; function Insert(Index: Integer): IXMLMember; property Member[Index: Integer]: IXMLMember read Get_Member; default; - function GetName: WideString; + function GetSchema: WideString; + function GetXPath: WideString; - procedure SetName(const Value: WideString); + procedure SetSchema(const Value: WideString); + procedure SetXPath(const Value: WideString); - property Name: WideString read GetName write SetName; + property Schema: WideString read GetSchema write SetSchema; + property XPath: WideString read GetXPath write SetXPath; end; IXMLMember = interface(IXMLNode) - ['{C242311F-B6B6-44B6-BAF2-40EBE6501963}'] + ['{A5C711D5-FEC5-4490-A36B-A2687AB39748}'] function GetName: WideString; procedure SetName(const Value: WideString); @@ -76,7 +85,7 @@ type a Document Element. } IXMLDocumentElements = interface(IXMLNodeCollection) - ['{A2036427-9FCE-41DF-B254-4BFBA42258AA}'] + ['{E6C9CBB2-7457-4597-939D-AAE9B1C5F42B}'] function Get_DocumentElement(Index: Integer): IXMLDocumentElement; function Add: IXMLDocumentElement; function Insert(Index: Integer): IXMLDocumentElement; @@ -85,12 +94,38 @@ type end; IXMLDocumentElement = interface(IXMLNode) - ['{DBC9940F-A0A3-42A4-83CF-AD90BD0892E5}'] - function GetName: WideString; + ['{93F6182F-4E03-420A-8E84-49F33DC29FA3}'] + function GetSchema: WideString; + function GetXPath: WideString; - procedure SetName(const Value: WideString); + procedure SetSchema(const Value: WideString); + procedure SetXPath(const Value: WideString); - property Name: WideString read GetName write SetName; + property Schema: WideString read GetSchema write SetSchema; + property XPath: WideString read GetXPath write SetXPath; + end; + + IXMLInterfaces = interface(IXMLNodeCollection) + ['{A18D3AFF-24FC-45FD-9583-15D9292249D2}'] + function Get_InterfaceName(Index: Integer): IXMLInterfaceName; + function Add: IXMLInterfaceName; + function Insert(Index: Integer): IXMLInterfaceName; + + property InterfaceName[Index: Integer]: IXMLInterfaceName read Get_InterfaceName; default; + end; + + IXMLInterfaceName = interface(IXMLNode) + ['{EB24ED8F-0D81-48D5-A420-438CAE003A23}'] + function GetHasSchema: Boolean; + function GetSchema: WideString; + function GetXPath: WideString; + + procedure SetSchema(const Value: WideString); + procedure SetXPath(const Value: WideString); + + property HasSchema: Boolean read GetHasSchema; + property Schema: WideString read GetSchema write SetSchema; + property XPath: WideString read GetXPath write SetXPath; end; @@ -103,6 +138,8 @@ type function GetEnumerations: IXMLEnumerations; function GetHasDocumentElements: Boolean; function GetDocumentElements: IXMLDocumentElements; + function GetHasInterfaces: Boolean; + function GetInterfaces: IXMLInterfaces; end; TXMLEnumerations = class(TXMLNodeCollection, IXMLEnumerations) @@ -122,9 +159,11 @@ type function Add: IXMLMember; function Insert(Index: Integer): IXMLMember; - function GetName: WideString; + function GetSchema: WideString; + function GetXPath: WideString; - procedure SetName(const Value: WideString); + procedure SetSchema(const Value: WideString); + procedure SetXPath(const Value: WideString); end; TXMLMember = class(TXMLNode, IXMLMember) @@ -145,9 +184,30 @@ type TXMLDocumentElement = class(TXMLNode, IXMLDocumentElement) protected - function GetName: WideString; + function GetSchema: WideString; + function GetXPath: WideString; - procedure SetName(const Value: WideString); + procedure SetSchema(const Value: WideString); + procedure SetXPath(const Value: WideString); + end; + + TXMLInterfaces = class(TXMLNodeCollection, IXMLInterfaces) + public + procedure AfterConstruction; override; + protected + function Get_InterfaceName(Index: Integer): IXMLInterfaceName; + function Add: IXMLInterfaceName; + function Insert(Index: Integer): IXMLInterfaceName; + end; + + TXMLInterfaceName = class(TXMLNode, IXMLInterfaceName) + protected + function GetHasSchema: Boolean; + function GetSchema: WideString; + function GetXPath: WideString; + + procedure SetSchema(const Value: WideString); + procedure SetXPath(const Value: WideString); end; @@ -199,6 +259,7 @@ procedure TXMLDataBindingHints.AfterConstruction; begin RegisterChildNode('Enumerations', TXMLEnumerations); RegisterChildNode('DocumentElements', TXMLDocumentElements); + RegisterChildNode('Interfaces', TXMLInterfaces); inherited; end; @@ -224,6 +285,17 @@ begin Result := (ChildNodes['DocumentElements'] as IXMLDocumentElements); end; +function TXMLDataBindingHints.GetHasInterfaces: Boolean; +begin + Result := Assigned(ChildNodes.FindNode('Interfaces')); +end; + + +function TXMLDataBindingHints.GetInterfaces: IXMLInterfaces; +begin + Result := (ChildNodes['Interfaces'] as IXMLInterfaces); +end; + procedure TXMLEnumerations.AfterConstruction; begin RegisterChildNode('Enumeration', TXMLEnumeration); @@ -274,14 +346,24 @@ begin Result := (AddItem(Index) as IXMLMember); end; -function TXMLEnumeration.GetName: WideString; +function TXMLEnumeration.GetSchema: WideString; begin - Result := AttributeNodes['Name'].Text; + Result := AttributeNodes['Schema'].Text; end; -procedure TXMLEnumeration.SetName(const Value: WideString); +function TXMLEnumeration.GetXPath: WideString; begin - SetAttribute('Name', Value); + Result := AttributeNodes['XPath'].Text; +end; + +procedure TXMLEnumeration.SetSchema(const Value: WideString); +begin + SetAttribute('Schema', Value); +end; + +procedure TXMLEnumeration.SetXPath(const Value: WideString); +begin + SetAttribute('XPath', Value); end; function TXMLMember.GetName: WideString; @@ -319,14 +401,75 @@ begin Result := (AddItem(Index) as IXMLDocumentElement); end; -function TXMLDocumentElement.GetName: WideString; +function TXMLDocumentElement.GetSchema: WideString; begin - Result := AttributeNodes['Name'].Text; + Result := AttributeNodes['Schema'].Text; end; -procedure TXMLDocumentElement.SetName(const Value: WideString); +function TXMLDocumentElement.GetXPath: WideString; begin - SetAttribute('Name', Value); + Result := AttributeNodes['XPath'].Text; +end; + +procedure TXMLDocumentElement.SetSchema(const Value: WideString); +begin + SetAttribute('Schema', Value); +end; + +procedure TXMLDocumentElement.SetXPath(const Value: WideString); +begin + SetAttribute('XPath', Value); +end; + +procedure TXMLInterfaces.AfterConstruction; +begin + RegisterChildNode('InterfaceName', TXMLInterfaceName); + + ItemTag := 'InterfaceName'; + ItemInterface := IXMLInterfaceName; + + inherited; +end; + +function TXMLInterfaces.Get_InterfaceName(Index: Integer): IXMLInterfaceName; +begin + Result := (List[Index] as IXMLInterfaceName); +end; + +function TXMLInterfaces.Add: IXMLInterfaceName; +begin + Result := (AddItem(-1) as IXMLInterfaceName); +end; + +function TXMLInterfaces.Insert(Index: Integer): IXMLInterfaceName; +begin + Result := (AddItem(Index) as IXMLInterfaceName); +end; + +function TXMLInterfaceName.GetHasSchema: Boolean; +begin + Result := Assigned(ChildNodes.FindNode('Schema')); +end; + + +function TXMLInterfaceName.GetSchema: WideString; +begin + Result := AttributeNodes['Schema'].Text; +end; + +function TXMLInterfaceName.GetXPath: WideString; +begin + Result := AttributeNodes['XPath'].Text; +end; + +procedure TXMLInterfaceName.SetSchema(const Value: WideString); +begin + SetAttribute('Schema', Value); +end; + +procedure TXMLInterfaceName.SetXPath(const Value: WideString); +begin + SetAttribute('XPath', Value); end; diff --git a/Units/XMLDataBindingGenerator.pas b/Units/XMLDataBindingGenerator.pas index 65b8187..e4a16ad 100644 --- a/Units/XMLDataBindingGenerator.pas +++ b/Units/XMLDataBindingGenerator.pas @@ -24,7 +24,7 @@ type TXMLDataBindingItemType = (itInterface, itEnumeration, itEnumerationMember, itProperty, itUnresolved, itComplexTypeAlias, itSimpleTypeAlias); - TXMLDataBindingInterfaceType = (ifElement, ifComplexType); + TXMLDataBindingInterfaceType = (ifElement, ifComplexType, ifEnumeration); TXMLDataBindingPropertyType = (ptSimple, ptItem); TXMLDataBindingOccurance = (boMinOccurs, boMaxOccurs); @@ -54,6 +54,7 @@ type procedure GenerateSchemaObjects(ASchema: TXMLDataBindingSchema; ARootDocument: Boolean); procedure GenerateElementObjects(ASchema: TXMLDataBindingSchema; ARootDocument: Boolean); procedure GenerateComplexTypeObjects(ASchema: TXMLDataBindingSchema); + procedure GenerateSimpleTypeObjects(ASchema: TXMLDataBindingSchema); function CheckElementOccurance(AElement: IXMLElementDef; AOccurance: TXMLDataBindingOccurance): Boolean; function IsElementOptional(AElement: IXMLElementDef): Boolean; @@ -88,8 +89,6 @@ type property SourceFileName: String read FSourceFileName write FSourceFileName; property SchemaCount: Integer read GetSchemaCount; property Schemas[Index: Integer]: TXMLDataBindingSchema read GetSchemas; - protected - procedure DoPostProcessItem(AItem: TXMLDataBindingItem); public constructor Create(); destructor Destroy(); override; @@ -234,7 +233,6 @@ type TXMLDataBindingEnumeration = class(TXMLDataBindingItem) private - FDataType: IXMLTypeDef; FMembers: TObjectList; function GetMemberCount(): Integer; @@ -242,10 +240,9 @@ type protected function GetItemType(): TXMLDataBindingItemType; override; public - constructor Create(AOwner: TXMLDataBindingGenerator; ASchemaItem: IXMLSchemaItem; ADataType: IXMLTypeDef; const AName: String); + constructor Create(AOwner: TXMLDataBindingGenerator; ASchemaItem: IXMLSchemaItem; AEnumerations: IXMLEnumerationCollection; const AName: String); destructor Destroy(); override; - property DataType: IXMLTypeDef read FDataType; property MemberCount: Integer read GetMemberCount; property Members[Index: Integer]: TXMLDataBindingEnumerationMember read GetMembers; end; @@ -574,9 +571,9 @@ begin for includeIndex := 0 to Pred(ASchema.IncludeCount) do GenerateSchemaObjects(ASchema.Includes[includeIndex], False); - GenerateElementObjects(ASchema, ARootDocument); GenerateComplexTypeObjects(ASchema); + GenerateSimpleTypeObjects(ASchema); end; @@ -627,6 +624,29 @@ begin end; +procedure TXMLDataBindingGenerator.GenerateSimpleTypeObjects(ASchema: TXMLDataBindingSchema); +var + schemaDef: IXMLSchemaDef; + simpleTypeIndex: Integer; + simpleType: IXMLSimpleTypeDef; + enumerationObject: TXMLDataBindingEnumeration; + +begin + schemaDef := ASchema.SchemaDef; + + for simpleTypeIndex := 0 to Pred(schemaDef.SimpleTypes.Count) do + begin + simpleType := schemaDef.SimpleTypes[simpleTypeIndex]; + + if simpleType.Enumerations.Count > 0 then + begin + enumerationObject := TXMLDataBindingEnumeration.Create(Self, simpleType, simpleType.Enumerations, simpleType.Name); + ASchema.AddItem(enumerationObject); + end; + end; +end; + + function TXMLDataBindingGenerator.CheckElementOccurance(AElement: IXMLElementDef; AOccurance: TXMLDataBindingOccurance): Boolean; function CheckParent(const ANode: IXMLNode): Boolean; @@ -719,7 +739,7 @@ begin if AElement.DataType.IsComplex then begin { Find data type. If not found, mark as "resolve later". } - Result := FindInterface(ASchema, AElement.DataTypeName, ifComplexType); + Result := FindInterface(ASchema, AElement.DataTypeName, ifComplexType); if not Assigned(Result) then begin @@ -735,6 +755,16 @@ begin complexAliasItem.Item := Result; ASchema.AddItem(complexAliasItem); end; + end else if AElement.DataType.Enumerations.Count > 0 then + begin + { References enumeration. } + Result := FindEnumeration(ASchema, AElement.DataTypeName); + + if not Assigned(Result) then + begin + Result := TXMLDataBindingUnresolvedItem.Create(Self, AElement, AElement.DataTypeName, ifEnumeration); + ASchema.AddItem(Result); + end; end else if AElement.IsGlobal then begin { The element is global, but only references a simple type. } @@ -751,7 +781,7 @@ begin if AElement.DataType.Enumerations.Count > 0 then begin { Enumeration } - enumerationObject := TXMLDataBindingEnumeration.Create(Self, AElement, AElement.DataType, AElement.Name); + enumerationObject := TXMLDataBindingEnumeration.Create(Self, AElement, AElement.DataType.Enumerations, AElement.Name); ASchema.AddItem(enumerationObject); Result := enumerationObject; end else if AElement.DataType.IsComplex then @@ -1009,11 +1039,16 @@ begin if not Assigned(AItem) then Exit; - referenceItem := FindInterface(ASchema, AItem.Name, AItem.InterfaceType); + if AItem.InterfaceType = ifEnumeration then + referenceItem := FindEnumeration(ASchema, AItem.Name) + else + begin + referenceItem := FindInterface(ASchema, AItem.Name, AItem.InterfaceType); - if (not Assigned(referenceItem)) and - (AItem.InterfaceType = ifElement) then - referenceItem := FindEnumeration(ASchema, AItem.Name); + if (not Assigned(referenceItem)) and + (AItem.InterfaceType = ifElement) then + referenceItem := FindEnumeration(ASchema, AItem.Name); + end; if Assigned(referenceItem) then ReplaceItem(AItem, referenceItem); @@ -1172,8 +1207,7 @@ var begin { Translate name } AItem.TranslatedName := TranslateItemName(AItem); - DoPostProcessItem(AItem); - + { Extract collections } if AItem.ItemType = itInterface then @@ -1263,13 +1297,6 @@ begin end; -procedure TXMLDataBindingGenerator.DoPostProcessItem(AItem: TXMLDataBindingItem); -begin - if Assigned(FOnPostProcessItem) then - FOnPostProcessItem(Self, AItem); -end; - - { TXMLDataBindingGeneratorItem } constructor TXMLDataBindingGeneratorItem.Create(AOwner: TXMLDataBindingGenerator); begin @@ -1528,18 +1555,17 @@ end; { TXMLDataBindingEnumeration } -constructor TXMLDataBindingEnumeration.Create(AOwner: TXMLDataBindingGenerator; ASchemaItem: IXMLSchemaItem; ADataType: IXMLTypeDef; const AName: String); +constructor TXMLDataBindingEnumeration.Create(AOwner: TXMLDataBindingGenerator; ASchemaItem: IXMLSchemaItem; AEnumerations: IXMLEnumerationCollection; const AName: String); var memberIndex: Integer; begin inherited Create(AOwner, ASchemaItem, AName); - FDataType := ADataType; FMembers := TObjectList.Create(); - for memberIndex := 0 to Pred(ADataType.Enumerations.Count) do - FMembers.Add(TXMLDataBindingEnumerationMember.Create(Owner, Self, ADataType.Enumerations.Items[memberIndex].Value)); + for memberIndex := 0 to Pred(AEnumerations.Count) do + FMembers.Add(TXMLDataBindingEnumerationMember.Create(Owner, Self, AEnumerations.Items[memberIndex].Value)); end; diff --git a/XSD/DataBindingHints.xsd b/XSD/DataBindingHints.xsd index 446482b..c10aff9 100644 --- a/XSD/DataBindingHints.xsd +++ b/XSD/DataBindingHints.xsd @@ -1,5 +1,5 @@ - + Contains hints and mappings for the data binding output @@ -22,7 +22,8 @@ - + + @@ -36,7 +37,24 @@ - + + + + + + + + + + + + + + + + + +