views:

714

answers:

1

In a SOAP client request, the header needs this line:

<NS2:Header Name="Foo">Bar<NS2:Header>

So I wrote a class which has two string properties:

  • the Content property - for the value of the element ("Bar")
  • the Name property - for the value of the attribute ("Foo")

The AS_ATTRIBUTE flag of the Name property should indicate that it is an XML "attribute".

   Header = class(TSoapHeader)
   private
     FContent: string;
     FName: string;
   published
     property Content: string read FContent write FContent;
     property Name: string read FName write FName stored AS_ATTRIBUTE;
   end;

and register with

   RemClassRegistry.RegisterXSClass(Header, MY_URI);
   RemClassRegistry.RegisterSerializeOptions(Header, [xoLiteralParam, 
xoSimpleTypeWrapper]);

The xoLiteralTypWrapper option indicates that the class should only 'wrap' the value Content property in the element and not add a nested element for it.

For Name := "Foo" and Content := "Bar", this will be the result XML code in the SOAP request:

<NS2:Header Name="Foo">
   <Content xsi:type="xsd:string">Bar</Content>
</NS2:Header>

The attribute is in the correct place, but the content value is in a nested tag which should not be here. If I remove the Name property from the class definition the Content property will look nice as the element content, like this:

<NS2:Header>Bar</NS2:Header>

It looks like a conflict between the two requirements - if I have the attribute, I will not get the xoSimpleTypeWrapper style.

+1  A: 

I haven't tried this so this is a speculation. Try overriding ObjectToSOAP and SOAPToObject method. In the help file it says

Override ObjectToSOAP to customize the way your application converts a TSOAPHeader descendant to its SOAP representation.

Again, I haven't tried this on compiler, but it could look like the following:

function Header.ObjectToSOAP(RootNode, ParentNode: IXMLNode; 
  const ObjConverter: IObjConverter; const Name, URI: InvString; 
  ObjConvOpts: TObjectConvertOptions; out RefID: InvString): IXMLNode;  
begin 
  ObjConvOpts := ObjConvOpts + [ocoDontSerializeProps]; 
  Result := inherited ObjectToSOAP(RootNode, ParentNode, ObjConverter, Name, URI, ObjConvOpts, RefID); 
  Result.Text := FContent; 
  Result.Attributes['Name'] := FName;
end;
eed3si9n
This looks very good - I will try it
mjustin
@mjustin, did it work?
eed3si9n
It works very well, sorry for the late answer
mjustin