diff --git a/Units/DelphiXMLDataBindingGenerator.pas b/Units/DelphiXMLDataBindingGenerator.pas index 2c73dd6..cbffb14 100644 --- a/Units/DelphiXMLDataBindingGenerator.pas +++ b/Units/DelphiXMLDataBindingGenerator.pas @@ -447,11 +447,15 @@ begin end; end; - if hasItem and (ASection = dxsInterface) then + if ASection = dxsInterface then begin - // #ToDo3 (MvR) 9-3-2008: namespace support? AStream.WriteLn('const'); - AStream.WriteLn(' TargetNamespace = '''';'); + AStream.WriteLn(' XMLSchemaInstanceURI = ''http://www.w3.org/2001/XMLSchema-instance'';'); + + if hasItem then + // #ToDo3 (MvR) 9-3-2008: namespace support? + AStream.WriteLn(' TargetNamespace = '''';'); + AStream.WriteLn(); AStream.WriteLn(); end; @@ -1063,6 +1067,7 @@ function TDelphiXMLDataBindingGenerator.WriteSchemaInterfaceProperty(AStream: TS var sourceCode: TNamedFormatStringList; writeOptional: Boolean; + writeNil: Boolean; writeTextProp: Boolean; propertyItem: TXMLDataBindingItem; dataTypeName: String; @@ -1075,13 +1080,19 @@ begin if AProperty = AItem.CollectionItem then Exit; - + { If the property has a collection, it's Count property will be enough to check if an item is present, no need to write a HasX method. } // #ToDo3 (MvR) 14-4-2008: move first check to XMLDataBindingGenerator ? - writeOptional := not Assigned(AProperty.Collection) and - AProperty.IsOptional and - (AMember in [dxmPropertyGet, dxmPropertyDeclaration]); + writeOptional := False; + writeNil := False; + + if AMember in [dxmPropertyGet, dxmPropertyDeclaration] then + begin + writeOptional := not Assigned(AProperty.Collection) and + AProperty.IsOptional; + writeNil := AProperty.IsNillable; + end; dataTypeName := ''; @@ -1139,6 +1150,9 @@ begin if writeOptional then sourceCode.Add(PropertyIntfMethodGetOptional); + if writeNil then + sourceCode.Add(PropertyIntfMethodGetNil); + if writeTextProp then sourceCode.Add(PropertyIntfMethodGetText); @@ -1164,6 +1178,9 @@ begin if writeOptional then sourceCode.Add(PropertyInterfaceOptional); + if writeNil then + sourceCode.Add(PropertyInterfaceNil); + if AProperty.IsReadOnly then begin if writeTextProp then @@ -1187,10 +1204,14 @@ begin dxmPropertyGet: begin WriteNewLine; - + + // #ToDo1 (MvR) 21-4-2008: optional attributes! if writeOptional then sourceCode.Add(PropertyImplMethodGetOptional); + if writeNil then + sourceCode.Add(PropertyImplMethodGetNil); + if writeTextProp then sourceCode.Add(PropertyImplMethodGetText); diff --git a/Units/DelphiXMLDataBindingResources.pas b/Units/DelphiXMLDataBindingResources.pas index ee0f204..3377256 100644 --- a/Units/DelphiXMLDataBindingResources.pas +++ b/Units/DelphiXMLDataBindingResources.pas @@ -73,12 +73,14 @@ const PropertyIntfMethodGetOptional = ' function GetHas%:s: Boolean;'; + PropertyIntfMethodGetNil = ' function GetIs%:sNil: Boolean;'; PropertyIntfMethodGetText = ' function Get%:sText: WideString;'; PropertyIntfMethodGet = ' function Get%:s: %:s;'; PropertyIntfMethodSetText = ' procedure Set%:sText(const Value: WideString);'; PropertyIntfMethodSet = ' procedure Set%:s(const Value: %:s);'; PropertyInterfaceOptional = ' property Has%:s: Boolean read GetHas%:s;'; + PropertyInterfaceNil = ' property Is%:sNil: Boolean read GetIs%:sNil;'; PropertyInterfaceTextReadOnly = ' property %:sText: WideString read Get%:sText;'; PropertyInterfaceReadOnly = ' property %:s: %:s read Get%:s;'; PropertyInterfaceText = ' property %:sText: WideString read Get%:sText write Set%:sText;'; @@ -90,6 +92,17 @@ const 'end;' + CrLf + '' + CrLf; + PropertyImplMethodGetNil = 'function TXML%:s.GetIs%:sNil: Boolean;' + CrLf + + 'var' + CrLf + + ' childNode: IXMLNode;' + CrLf + + '' + CrLf + + 'begin' + CrLf + + ' childNode := ChildNodes[''%:s''];' + CrLf + + ' Result := childNode.HasAttribute(''nil'', XMLSchemaInstanceURI) and' + CrLf + + ' StrToBoolDef(childNode.GetAttributeNS(''nil'', XMLSchemaInstanceURI), False);' + CrLf + + 'end;' + CrLf + + '' + CrLf; + PropertyImplMethodGetText = 'function TXML%:s.Get%:sText: WideString;' + CrLf + 'begin' + CrLf + ' Result := ChildNodes[''%:s''].NodeValue;' + CrLf + diff --git a/Units/XMLDataBindingGenerator.pas b/Units/XMLDataBindingGenerator.pas index a3e511d..6ff221c 100644 --- a/Units/XMLDataBindingGenerator.pas +++ b/Units/XMLDataBindingGenerator.pas @@ -14,6 +14,7 @@ type TXMLDataBindingEnumerationMember = class; TXMLDataBindingEnumeration = class; TXMLDataBindingProperty = class; + TXMLDataBindingItemProperty = class; TXMLDataBindingUnresolvedItem = class; @@ -243,6 +244,7 @@ type private FIsAttribute: Boolean; FIsOptional: Boolean; + FIsNillable: Boolean; FIsRepeating: Boolean; FCollection: TXMLDataBindingInterface; protected @@ -253,6 +255,7 @@ type public property IsAttribute: Boolean read FIsAttribute write FIsAttribute; property IsOptional: Boolean read FIsOptional write FIsOptional; + property IsNillable: Boolean read FIsNillable write FIsNillable; property IsReadOnly: Boolean read GetIsReadOnly; property IsRepeating: Boolean read FIsRepeating write FIsRepeating; property PropertyType: TXMLDataBindingPropertyType read GetPropertyType; @@ -269,6 +272,7 @@ type function GetPropertyType(): TXMLDataBindingPropertyType; override; public constructor Create(AOwner: TXMLDataBindingGenerator; ASchemaItem: IXMLSchemaItem; const AName: String; ADataType: IXMLTypeDef); + constructor CreateFromAlias(AOwner: TXMLDataBindingGenerator; AProperty: TXMLDataBindingItemProperty; ADataType: IXMLTypeDef); property DataType: IXMLTypeDef read FDataType; end; @@ -338,6 +342,7 @@ const MaxOccursUnbounded = 'unbounded'; UseOptional = 'optional'; CollectionPostfix = 'List'; + AttributeNillable = 'nillable'; @@ -624,8 +629,7 @@ function TXMLDataBindingGenerator.CheckElementOccurance(AElement: IXMLElementDef if Supports(ANode, IXMLElementCompositor, compositor) then begin case AOccurance of - boMinOccurs: Result := (compositor.MinOccurs = 0) or - (compositor.CompositorType = ctChoice); + boMinOccurs: Result := (compositor.MinOccurs = 0); boMaxOccurs: Result := (compositor.MaxOccurs = MaxOccursUnbounded) or (compositor.MaxOccurs > 1); end; @@ -669,7 +673,7 @@ var begin Result := False; - if Supports(AElement, IXMLElementCompositor, compositor) then + if Supports(AElement.ParentNode, IXMLElementCompositor, compositor) then Result := (compositor.CompositorType = ctChoice) and (compositor.ElementDefs.Count > 1); end; @@ -766,6 +770,7 @@ end; procedure TXMLDataBindingGenerator.ProcessChildElement(ASchema: TXMLDataBindingSchema; AElement: IXMLElementDef; AInterface: TXMLDataBindingInterface); var + actualElement: IXMLElementDef; propertyType: TXMLDataBindingItem; propertyItem: TXMLDataBindingProperty; @@ -787,6 +792,16 @@ begin IsChoice(AElement); propertyItem.IsRepeating := IsElementRepeating(AElement); + + actualElement := AElement; + while Assigned(actualElement) and Assigned(actualElement.Ref) do + actualElement := actualElement.Ref; + + if AElement.HasAttribute(AttributeNillable) then + propertyItem.IsNillable := StrToBoolDef(AElement.Attributes[AttributeNillable], False) + else if actualElement.HasAttribute(AttributeNillable) then + propertyItem.IsNillable := StrToBoolDef(actualElement.Attributes[AttributeNillable], False); + AInterface.AddProperty(propertyItem); end; end; @@ -1440,10 +1455,7 @@ begin if itemProperty.Item = AOldItem then begin { Replace item property with simple property } - simpleProperty := TXMLDataBindingSimpleProperty.Create(Owner, - itemProperty.SchemaItem, - itemProperty.Name, - TXMLDataBindingSimpleTypeAliasItem(AOldItem).DataType); + simpleProperty := TXMLDataBindingSimpleProperty.CreateFromAlias(Owner, itemProperty, TXMLDataBindingSimpleTypeAliasItem(AOldItem).DataType); { FProperties owns itemProperty and will free it } FProperties[propertyIndex] := simpleProperty; @@ -1553,6 +1565,17 @@ begin end; +constructor TXMLDataBindingSimpleProperty.CreateFromAlias(AOwner: TXMLDataBindingGenerator; AProperty: TXMLDataBindingItemProperty; ADataType: IXMLTypeDef); +begin + Create(AOwner, AProperty.SchemaItem, AProperty.Name, ADataType); + + IsAttribute := AProperty.IsAttribute; + IsOptional := AProperty.IsOptional; + IsNillable := AProperty.IsNillable; + IsRepeating := AProperty.IsRepeating; +end; + + function TXMLDataBindingSimpleProperty.GetIsReadOnly(): Boolean; begin Result := False;