5
votes

I am completely new to web services, but not new to Delphi.

I am importing a WSDL file into Delphi 2010 with the "WSDL Importer" wizard. The WSDL file contains some "attributeGroup" tags which Delphi completely ignores, which is presumably a bug, although I haven't yet found an entry on Quality Central for this issue, only mentions in forums like here and here.

My question has several parts:

  1. What is the best workaround?
  2. I have written a Python script to format the WSDL file such that all references to attributeGroup tags are replaced with the declaration of the attributes defined in the attributeGroups; in other words, flattening the references. The output is successfully imported into Delphi via the "WSDL importer" wizard, and looks correct, but I have yet to test whether the messages constructed via this new WSDL file will work correctly. Is this strategy likely to be viable, or should I quit now and move onto something else more productive?

Update

Based on my experiences, and the answers in this question, I decided to go the wrapper route with a C# console application that eats JSON input data and outputs JSON reply data. A Delphi app drives the C# app. The SOAP part of the whole thing is now effortless, and "just works" in C#.NET, and the rest of the functionality is handled well by Delphi. I would recommend this route to anyone else with similar problems. I did try exporting a C# SOAP assembly as a COM library, and connecting to that from Delphi, but it became very complex, because the SOAP specification in my particular app is large and somewhat complex.

4
So, you can add that QC Report yourself...Fabricio Araujo
Some detailed examples would help understand your issue.in my codemj2008
@mj2008: Delphi WSDL importer completely ignores "attributeGroup" tag references in WSDL files...how would an example help to illustrate this?Caleb Hattingh
You are asking a very specialist question, and while I have used these things a fair bit, I need reminding of the details. The number of answers indicates that others are not able to help, so perhaps time to provide more so we don't have to do the research ourselves. But up to you of course.mj2008

4 Answers

2
votes

Ok, this one took a while.

According to this post, there are certain tags that the .NET wsdl.exe tool just won't recognize when importing a wsdl file. According to MSDN:

attributeGroup: Ignored. DataContractSerializer does not support use of xs:group, xs:attributeGroup, and xs:attribute. These declarations are ignored as children of xs:schema, but cannot be referenced from within complexType or other supported constructs.

This behaviour is also described (albeit in a very hard-to-understand manner) on one of the MSDN blogs. In my specific case, the particular part of the wsdl file causing the problem looks like this:

 <xs:complexType name="PhonesType">
     <xs:annotation>
         <xs:documentation xml:lang="en">Provides detailed phone information.</   xs:documentation>
     </xs:annotation>
     <xs:sequence>
         <xs:element maxOccurs="unbounded" name="Phone">
             <xs:annotation>
                 <xs:documentation xml:lang="en">Used to pass detailed phone information.</xs:documentation>
             </xs:annotation>
             <xs:complexType>
                 <xs:attributeGroup ref="TelephoneInfoGroup"/>
                 <xs:attributeGroup ref="ID_OptionalGroup">
                     <xs:annotation>
                         <xs:documentation xml:lang="en">The ID attribute in this group is a unique identifying value assigned by the creating system and may be used to reference a primary-key value within a database or in a particular implementation.</xs:documentation>
                     </xs:annotation>
                 </xs:attributeGroup>
             </xs:complexType>
         </xs:element>
     </xs:sequence>
 </xs:complexType>

It seems that the <xs:attributeGroup ref="TelephoneInfoGroup"/> is being ignored by the .NET wsdl.exe tool, just like it was being ignored by the Delphi wsdl importer. In such a situation, where importing fails in both Delphi and .NET, the wsdl file probably has to be changed, and that means I will have to use my home-made python ref-flattener after all.

1
votes

We had a similar problem with Delphi 2009 and a standard Soap service (CRM). It was not related to attributeGroup. We found so many incompatibilities that we finally decided to use a small C# application as a proxy for the real .Net based service.

1
votes

I was the poster of the first reference you give. I think I found out that this bug has never been fixed.

I later posted another question on the Embarcadero Developer Network where Nick Hodges said that

We are concentrating on client development [...] if you are looking to build SOAP servers, then I'd suggest that you also give Delphi Prism a look.

We decided to switch to C# for development of our SOAP servers. I decided to let the service talk to a database, which is then accessed by our Delphi application.

Later I ran into problems with client development under Delphi as well, so we're doing that in C#, too. This time the C# class is com visible and can be accessed from Delphi. Seems to work fine.

Regards, Miel.

0
votes

The Delphi WSDL importer can't handle <xsd:attributeGroup ref="..."> elements, but you can replace those with the actual attributes that are referenced, which the importer can deal with.

Below is a PowerShell script that does this replacement.

The script is unpolished. It's just what I created for my own needs. It may work for you too, or at least it should give you a starting point.

$xsdPath = "E:\scratch\InputFile.wsdl"

# Note: Must be full path.
$outPath = "E:\scratch\OutputFile.wsdl"

$xsd = [xml](gc $xsdPath)

$ns = @{xsd="http://www.w3.org/2001/XMLSchema"}

$attrGroupDefs = $xsd | 
    Select-Xml -Namespace $ns -XPath "//xsd:schema/xsd:attributeGroup" |
    select -ExpandProperty Node

$attrGroupRefs = $xsd |
    Select-Xml -Namespace $ns -XPath "//xsd:complexType/xsd:attributeGroup" |
    select -ExpandProperty Node

$attrGroupRefs | % { 
    # the thing to be replaced
    $ref = $_

    $refParent = $ref.ParentNode

    $namespace, $name = $_.ref -split ":"
    $attrs = $attrGroupDefs | ? name -eq $name | select -ExpandProperty attribute

    # remove the reference
    $refParent.RemoveChild($ref)

    # add the actual definitions
    $attrs | % {
        $newNode = $_.CloneNode($true)
        $refParent.AppendChild($newNode)
    }
}

$xsd.Save($outPath)