Groups > Borland > Delphi web services WSDL > Re: Translation of array




Translation of array

Translation of array
Fri, 15 Feb 2008 12:35:40 -060
D2007, importing wsdl, wsdl looks like this:

- <s:complexType name="ArrayOfChoice1">
- <s:choice minOccurs="0" maxOccurs="unbounded">
  <s:element minOccurs="1" maxOccurs="1"
name="ProductModifier" 
nillable="true" type="s1:ProductModifier" />
  <s:element minOccurs="1" maxOccurs="1"
name="ProductChoice" 
nillable="true" type="s1:ProductChoice" />
  <s:element minOccurs="1" maxOccurs="1"
name="ProductInput" nillable="true" 
type="s8:ProductInput" />
  </s:choice>
  </s:complexType>

translated to below. It looks to me like ArrayOfChoice1 should have been 
tranlated to an array of Choice1 where Choice1 is the class but 
ArrayOfChoice1 is an array. Not sure if the wsdl is a proper definition or 
not.

  // 
************************************************************************ //
  // XML       : ArrayOfChoice1, global, <complexType>
  // Namespace : 
http://www.bvsoftware.com/bvc5/schemas/2005/09/01/Catalog/Product
  // 
************************************************************************ //
  ArrayOfChoice1 = class(TRemotable)
  private
    FProductModifier: ProductModifier2;
    FProductModifier_Specified: boolean;
    FProductChoice: ProductChoice2;
    FProductChoice_Specified: boolean;
    FProductInput: ProductInput;
    FProductInput_Specified: boolean;
    procedure SetProductModifier(Index: Integer; const AProductModifier2: 
ProductModifier2);
    function  ProductModifier_Specified(Index: Integer): boolean;
    procedure SetProductChoice(Index: Integer; const AProductChoice2: 
ProductChoice2);
    function  ProductChoice_Specified(Index: Integer): boolean;
    procedure SetProductInput(Index: Integer; const AProductInput: 
ProductInput);
    function  ProductInput_Specified(Index: Integer): boolean;
  public
    destructor Destroy; override;
  published
    property ProductModifier: ProductModifier2  Index (IS_OPTN or IS_NLBL) 
read FProductModifier write SetProductModifier stored 
ProductModifier_Specified;
    property ProductChoice:   ProductChoice2    Index (IS_OPTN or IS_NLBL) 
read FProductChoice write SetProductChoice stored ProductChoice_Specified;
    property ProductInput:    ProductInput      Index (IS_OPTN or IS_NLBL) 
read FProductInput write SetProductInput stored ProductInput_Specified;
  end;

Wayne
Post Reply
Re: Translation of array
Fri, 15 Feb 2008 16:10:27 -080
Hello,

Yes, your assessment is correct. I mentioned this in other posts recently:


http://groups.google.com/group/borland.public.delphi.webservices.wsdl/msg/86d0fb
ac46d93741

http://groups.google.com/group/borland.public.delphi.webservices.soap/msg/5a560f
4c3ce86f62

Basically we do not support cardinality specified on compositor nodes
(choice, sequence or all). Initially there was a problem retrieving
compositor information from the elements - specially when the compositor
nodes are nested. This issue remains (it's something that the folks working
on the xml area are looking at). However, in the case you mentioned, there's
no nesting of compositor nodes. That one is just a plain failure on the
importer's side.

Sometimes it's easy to rewrite the schema to avoid cardinality on the
compositor node but in your case (with an unbounded choice) that approach
won't work.

In this particular case I'm afraid you might need to take over the
importer's output and edit. Something along the lines of the following
should work (NOTE: I have not tried this out but am happy to investigate
further if this does not work):


 Choice1 = class(TRemotable)
   private
     FProductModifier: ProductModifier2;
     FProductModifier_Specified: boolean;
     FProductChoice: ProductChoice2;
     FProductChoice_Specified: boolean;
     FProductInput: ProductInput;
     FProductInput_Specified: boolean;
     procedure SetProductModifier(Index: Integer; const AProductModifier2:
ProductModifier2);
     function  ProductModifier_Specified(Index: Integer): boolean;
     procedure SetProductChoice(Index: Integer; const AProductChoice2:
ProductChoice2);
     function  ProductChoice_Specified(Index: Integer): boolean;
     procedure SetProductInput(Index: Integer; const AProductInput:
ProductInput);
     function  ProductInput_Specified(Index: Integer): boolean;
   public
     destructor Destroy; override;
   published
     property ProductModifier: ProductModifier2  Index (IS_OPTN or IS_NLBL)
read FProductModifier write SetProductModifier stored
ProductModifier_Specified;
     property ProductChoice:   ProductChoice2    Index (IS_OPTN or IS_NLBL)
read FProductChoice write SetProductChoice stored ProductChoice_Specified;
     property ProductInput:    ProductInput      Index (IS_OPTN or IS_NLBL)
read FProductInput write SetProductInput stored ProductInput_Specified;
 end;


 ArrayOfChoice1 = array of Choice1;

 ArrayOfChoice = class(TRemotable)
   private
    FArrayOfChoice: ArrayOfChoice1;
   public
     destructor Destroy; override;
   published
    property ArrayOfChoice: ArrayOfChoice1 Index (IS_NLBL or IS_UNBD) read
FArrayOfChoice write FArrayOfChoice;
 end;

Oh, and make sure to tag Choice1 as a holder class:

initialization
  RemClassRegistry.RegisterSerializeOptions(TypeInfo(Choice1),
[xoHolderClass]);


Let me know if the above does not work. I hope to have some time to work on
compositor nodes with cardinality specified soon.

Cheers,

Bruneau.

Post Reply
Re: Translation of array
Fri, 15 Feb 2008 16:21:49 -080
OK, since I already had the code I posted, I went ahead and wrote a little
test. Here's what I did:

#1. I mapped the leaf-node types to built-in types for simplicity (this
should not affect the rest of the code);

type
 ProductModifier2 = string;
 ProductChoice2 = integer;
 ProductInput = string;



#2. I registered the types I posted in the previous post:

initialization
  RemClassRegistry.RegisterXSInfo(TypeInfo(ArrayOfChoice), 'urn:test-ns',
'ArrayOfChoice');
  RemClassRegistry.RegisterXSInfo(TypeInfo(Choice1), 'urn:test-ns',
'Choice1');
  RemClassRegistry.RegisterSerializeOptions(TypeInfo(Choice1),
[xoHolderClass]);



#3. I wrote a little piece of code that creates an instance of
'ArrayOfChoice' as in:

procedure TForm6.Button2Click(Sender: TObject);
var
  AC: ArrayOfChoice;
  I: Integer;
begin
  AC := ArrayOfChoice.Create;
  try
    SetLength(AC.FArrayOfChoice, 10);
    for I := 0 to Length(AC.FArrayOfChoice) - 1 do
    begin
      AC.FArrayOfChoice[I] := Choice1.Create;
      if ((I mod 3) = 0) then
        AC.FArrayOfChoice[I].ProductModifier := 'Modifier' + IntToStr(I)
      else if ((I mod 3) = 1) then
        AC.FArrayOfChoice[I].ProductInput := 'Input' + IntToStr(I)
      else
        AC.FArrayOfChoice[I].ProductChoice := I;
    end;
    Memo1.Text := ObjToXML(AC, CloneConverter(HTTPRIO1));
  finally
    AC.Free;
  end;
end;


#4 The ObjToXML call above is just a little helper routine that uses the
SOAP runtime to generate XML from a TRemotable type. In essence I'm
exercising the serialization logic but omitting the HTTP posting/transport
section.


#5. Here's the resulting XML:

<?xml version="1.0"?>
<Root xmlns="urn:TestNamespace"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ArrayOfChoice xmlns="urn:test-ns">
    <ProductModifier>Modifier0</ProductModifier>
    <ProductInput>Input1</ProductInput>
    <ProductChoice>2</ProductChoice>
    <ProductModifier>Modifier3</ProductModifier>
    <ProductInput>Input4</ProductInput>
    <ProductChoice>5</ProductChoice>
    <ProductModifier>Modifier6</ProductModifier>
    <ProductInput>Input7</ProductInput>
    <ProductChoice>8</ProductChoice>
    <ProductModifier>Modifier9</ProductModifier>
  </ArrayOfChoice>
</Root>


The contents of each element will be different in your case as you won't be
using the mapping to simple types but the overall <ArrayOfChoice> as an
unbounded choice of one of 3 elements should be working.

Please let me know if this does not work for you.

Cheers,

Bruneau.

Post Reply
Re: Translation of array
Fri, 15 Feb 2008 18:36:13 -060
Hi Bruneau,

Thanks for the quick repsonse. I played around a bit trying to do in a way 
what you did, but not being a wizard at this stuff did not quite get it 
right. I will try to implement what you have and post back how it goes.

Thanks.

Wayne

"Jean-Marie Babet" <bbabet@borland.com> wrote in message 
news:47b62934$1@newsgroups.borland.com...
> Hello,
>
> Yes, your assessment is correct. I mentioned this in other posts recently:
>
>
>
http://groups.google.com/group/borland.public.delphi.webservices.wsdl/msg/86d0fb
ac46d93741
>
>
http://groups.google.com/group/borland.public.delphi.webservices.soap/msg/5a560f
4c3ce86f62
>
> Basically we do not support cardinality specified on compositor nodes
> (choice, sequence or all). Initially there was a problem retrieving
> compositor information from the elements - specially when the compositor
> nodes are nested. This issue remains (it's something that the folks 
> working
> on the xml area are looking at). However, in the case you mentioned, 
> there's
> no nesting of compositor nodes. That one is just a plain failure on the
> importer's side.
>
> Sometimes it's easy to rewrite the schema to avoid cardinality on the
> compositor node but in your case (with an unbounded choice) that approach
> won't work.
>
> In this particular case I'm afraid you might need to take over the
> importer's output and edit. Something along the lines of the following
> should work (NOTE: I have not tried this out but am happy to investigate
> further if this does not work):
>
>
> Choice1 = class(TRemotable)
>   private
>     FProductModifier: ProductModifier2;
>     FProductModifier_Specified: boolean;
>     FProductChoice: ProductChoice2;
>     FProductChoice_Specified: boolean;
>     FProductInput: ProductInput;
>     FProductInput_Specified: boolean;
>     procedure SetProductModifier(Index: Integer; const AProductModifier2:
> ProductModifier2);
>     function  ProductModifier_Specified(Index: Integer): boolean;
>     procedure SetProductChoice(Index: Integer; const AProductChoice2:
> ProductChoice2);
>     function  ProductChoice_Specified(Index: Integer): boolean;
>     procedure SetProductInput(Index: Integer; const AProductInput:
> ProductInput);
>     function  ProductInput_Specified(Index: Integer): boolean;
>   public
>     destructor Destroy; override;
>   published
>     property ProductModifier: ProductModifier2  Index (IS_OPTN or IS_NLBL)
> read FProductModifier write SetProductModifier stored
> ProductModifier_Specified;
>     property ProductChoice:   ProductChoice2    Index (IS_OPTN or IS_NLBL)
> read FProductChoice write SetProductChoice stored ProductChoice_Specified;
>     property ProductInput:    ProductInput      Index (IS_OPTN or IS_NLBL)
> read FProductInput write SetProductInput stored ProductInput_Specified;
> end;
>
>
> ArrayOfChoice1 = array of Choice1;
>
> ArrayOfChoice = class(TRemotable)
>   private
>    FArrayOfChoice: ArrayOfChoice1;
>   public
>     destructor Destroy; override;
>   published
>    property ArrayOfChoice: ArrayOfChoice1 Index (IS_NLBL or IS_UNBD) read
> FArrayOfChoice write FArrayOfChoice;
> end;
>
> Oh, and make sure to tag Choice1 as a holder class:
>
> initialization
>  RemClassRegistry.RegisterSerializeOptions(TypeInfo(Choice1),
> [xoHolderClass]);
>
>
> Let me know if the above does not work. I hope to have some time to work 
> on
> compositor nodes with cardinality specified soon.
>
> Cheers,
>
> Bruneau.
>
> 
Post Reply
Re: Translation of array
Sat, 16 Feb 2008 01:03:53 +010
Hi.
IMO the wsdl-complex type looks ok.
I suppose that the problem is that as of the wsdl the ArrayOfChoice1 
can consist of three different types (ProductModifier, ProductChoice and 
ProductInput) which can appear in any order - but as of the generated 
Pascal source it could perhabs be that only one type is accepted (or 
parsed)? You could try to see what happens if you stick to one type 
(like having in your array only ProductInput-type). If you receive then 
more than the first element it is probably a problem with complex type 
and array of choice in Webservices with Delphi. Somehow there is any 
representation of wsdl-choice missing in the pascal code - at least 
that's what I think. But I do not know what happens internaly.

I would expect something like this being generated but it would need to 
be reflected with the proper parsing of the soap-response Delphi internally:

ArrayOfChoice2 = class(TObject);
ProductModifier = class(ArrayOfChoice2);
ProductChoice = class(ArrayOfChoice2);
ProductInput = class(ArrayOfChoice2);

  ArrayOfChoice1 = class(TRemotable)
  private
    !!!this inserted!!!	
    FArrayOfChoice1: ArrayOfChoice2;
    !!!end of insertion!!!
    FProductModifier: ProductModifier2;
    FProductModifier_Specified: boolean;
    FProductChoice: ProductChoice2;
    FProductChoice_Specified: boolean;
    FProductInput: ProductInput;
    FProductInput_Specified: boolean;
    !!!this inserted!!!	
    procedure SetArrayOfChoice1(Index: Integer; const AArrayOfChoice2: 
ArrayOfChoice2);
    function  ArrayOfChoice1_Specified(Index: Integer): boolean;
    !!!end of insertion!!!
    procedure SetProductModifier(Index: Integer; const 
AProductModifier2: ProductModifier2);
    function  ProductModifier_Specified(Index: Integer): boolean;
    procedure SetProductChoice(Index: Integer; const AProductChoice2: 
ProductChoice2);
    function  ProductChoice_Specified(Index: Integer): boolean;
    procedure SetProductInput(Index: Integer; const AProductInput: 
ProductInput);
    function  ProductInput_Specified(Index: Integer): boolean;
  public
    destructor Destroy; override;
  published
    !!!this inserted!!!
    property ArrayOfChoice1: ArrayOfChoice2 Index ((IS_OPTN or IS_NLBL) 
read FArrayofChoice1 write SetArrayOfChoice1 stored 
ArrayOfChoice1_Specified;
    !!!end of insertion!!!
    property ProductModifier: ProductModifier2  Index (IS_OPTN or 
IS_NLBL) read FProductModifier write SetProductModifier stored 
ProductModifier_Specified;
    property ProductChoice:   ProductChoice2    Index (IS_OPTN or 
IS_NLBL) read FProductChoice write SetProductChoice stored 
ProductChoice_Specified;
    property ProductInput:    ProductInput      Index (IS_OPTN or 
IS_NLBL) read FProductInput write SetProductInput stored 
ProductInput_Specified;
  end;

That way we would have the generalized array item which consists of 
specialized choice-items.
Are WSDLs with complex types and choice a general problem?
I heard that most people construct and parse the soap requests and 
responses in web service settings on their own - which is suposed to be 
not very well supported with Delphi. In my opinion there is a lack of 
easy ways for late binding of webservices to runtime artefacts. But I am 
not an expert to judge that.

Further - I am not sure if I understood you right.

Regards

Roland
Post Reply
<< Previous 1 2 Next >>
( Page 1 of 2 )
about | contact