OMG! Потребовалось много кофе и много недосыпания, но мне удалось решить мою проблему! Это тоже довольно просто ...
Сначала я импортирую WSDL, как и ожидалось. Это сгенерирует несколько TRemotable классов. Затем для каждого TRemotable, которому требуется другое пространство имен, я переопределяю метод ObjectToSOAP ()! (И включите XMLIntf в источник WSDL.) В моем случае с кодом, подобным этому, для нескольких типов, которые можно удалить:
function AL2.ObjectToSOAP( RootNode, ParentNode: IXMLNode; const ObjConverter: IObjConverter; const NodeName, NodeNamespace, ChildNamespace: InvString; ObjConvOpts: TObjectConvertOptions; out RefID: InvString ): IXMLNode;
begin
Result := inherited ObjectToSOAP( RootNode, ParentNode, ObjConverter, NodeName, '', '', ObjConvOpts, RefID );
end;
Который работал в Delphi XE. В Delphi 2007 мне пришлось использовать модули XMLIntf и XMLDoc плюс этот код для типа ввода:
function ContractdocumentInType.ObjectToSOAP(RootNode, ParentNode: IXMLNode; const ObjConverter: IObjConverter; const Name, URI: InvString; ObjConvOpts: TObjectConvertOptions; out RefID: InvString): IXMLNode;
procedure AlterChildren(Child: IXMLNode);
var
I: Integer;
begin
if (Child.NodeType = ntElement) then Child.SetAttributeNS('xmlns', '', '');
for I := 0 to Pred(Child.ChildNodes.Count) do
AlterChildren(Child.ChildNodes[I]);
end;
begin
Result := inherited ObjectToSOAP(RootNode, ParentNode, ObjConverter, Name, '', ObjConvOpts, RefID);
AlterChildren(Result);
end;
Это хак, на мой взгляд. Но это не очень грязный. Это немного экспериментирует, собирая запросы и ответы SOAP, чтобы проверить их содержимое и посмотреть, использует ли он правильные пространства имен. К сожалению, Delphi XE справляется с этим намного лучше, чем Delphi 2007.
Тем не менее, я оставляю этот вопрос открытым для любых лучших решений ...
Кстати, чтобы добавить col:
к выводу, мне также пришлось изменить эту строку в WSDL RemClassRegistry.RegisterXSClass(Calculate, 'http://colan.ogconnect.service.wzp/', 'Calculate');
на эту: RemClassRegistry.RegisterXSClass(Calculate, 'http://colan.ogconnect.service.wzp/', 'cal:Calculate');
. Результат тогда становится <cal:Calculate xmlns:cal="http://example.webservice/">
. Однако больше ничего не нужно делать: переместить этот xmlns:cal
в заголовок xml. Но как сейчас, это работает для меня.
Еще одно примечание: для WSDL я использовал следующие настройки: «One Outparam is return», «Разматывать литеральные параметры», «Создать деструкторы», «Предупреждающие комментарии», « испускать литеральные типы », «Отобразить строку в широкую строку». Другие варианты: «Создать подробную информацию о типах и интерфейсах», «Игнорировать типы портов с помощью HTTP-привязок», «Проверять элементы перечисления», «Импортировать типы ошибок», «Импортировать типы заголовков», «Обработать включенные и импортированные схемы», «Создать» псевдоним класса как типы классов ',' параметры Allow Out 'и' Process nillable и необязательные элементы '. Литеральные типы emit были практичны, потому что они генерируют класс вокруг единственного метода, который я вызывал. К сожалению, это тоже мало поможет, хотя класс поможет вам изменить запрос SOAP на верхнем уровне в конверте, переопределив метод ObjectToSOAP ().
Создание самого конверта находится в модуле SOAPEnv и он используется в модуле OPToSOAPDomConv. К сожалению, я не нашел простого способа получить доступ к самому конверту, чтобы изменить заголовок и добавить это дополнительное пространство имен. С другой стороны, я мог бы переопределить класс TSOAPDomConv своей собственной версией, которая добавляет дополнительное пространство имен. Но код работает для меня сейчас, и, как сказал мне мой отец, когда он научил меня программировать: никогда не исправляйте ничего, что не сломалось.