mvantellingen / python-zeep

A Python SOAP client
http://docs.python-zeep.org
Other
1.87k stars 578 forks source link

Client only parses xsd type extensions one level #1407

Open atlantis-dsf opened 4 months ago

atlantis-dsf commented 4 months ago
  1. Zeep Version 4.2.1 (Python 3.11.2)
  2. The WSDL you are using
  3. And most importantly, a runnable example script which exposes the problem.

Hello, I know the issue looks long but that's just from the example code, the issue title describes the bug exactly, I only add explanations to "Current situation", "Expected behavior" and "Tried solutions" The example code as well as excerpts from the .xsd file you can find under EXAMPLE CODE

I really appreciate you creating and maintaining this package, I don't know what else we would do If you can solve this and you have a rate in mind let me know

Current situation: zeep.Client recognizes the extension of a type, so the ClassificationType generated by zeep does extend the RegistryObjectType. But the RegistryObjectType extends the IdentifiableType, and the ClassificationType generated doesn't include the attributes/elements of the IdentifiableType (in particular Slot[] and id)

Expected behavior: zeep.Client traverses the whole extension hierarchy

Tried solutions:

EXAMPLE CODE

# example script
from zeep import Client
from zeep.settings import Settings

# EntitiesForbidden: EntitiesForbidden(name='dsig', content='http://www.w3.org/2000/09/xmldsig#')
client_settings = Settings(strict=False, xml_huge_tree=True, forbid_entities=False)

wsdl_src = "https://raw.githubusercontent.com/gematik/epa-ps-sim/main/epa-fm-java-api/src/main/resources/schemas/conn/phrs/PHRService_V2_0_1.wsdl"

client = Client(wsdl=wsdl_src, settings=client_settings)

rim_qname = "{urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0}"
ClassificationType = client.get_type(rim_qname + "ClassificationType")

print("ClassificationType extends ", ClassificationType._extension_types)

RegistryObjectType = client.get_type(rim_qname + ClassificationType._extension_types[0].__name__)

print("RegistryObjectType extends ", RegistryObjectType._extension_types)

IdentifiableType = client.get_type(rim_qname + RegistryObjectType._extension_types[0].__name__)

print("IdentifiableType extends ", IdentifiableType._extension_types)

print("IdentifiableType base object: ", IdentifiableType(Slot=[]))

print("ClassificationType base object: ", ClassificationType())

# ClassificationType(Slot=[]) fails with TypeError
# TypeError: {urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0}ClassificationType() got an unexpected keyword argument 'Slot'. Signature: ...
try:
    ClassificationType(Slot=[])
except TypeError as e:
    print(e)

All the relevant types come from the "lib-ihe-xds" repository, from the ext\ebRS\rim.xsd type definition file

The relevant excerpts from the WSDL for convenience

<complexType name="ClassificationType">
    <annotation>
        <documentation xml:lang="en">
    Classification is the mapping of the same named interface in ebRIM.
    It extends RegistryObject.
    A Classification specifies references to two registry entrys.
    The classifiedObject is id of the Object being classified.
    The classificationNode is id of the ClassificationNode classying the object
    </documentation>
    </annotation>
    <complexContent>
        <extension base="tns:RegistryObjectType">
            <attribute name="classificationScheme" type="tns:referenceURI" use="optional"/>
            <attribute name="classifiedObject" type="tns:referenceURI" use="required"/>
            <attribute name="classificationNode" type="tns:referenceURI" use="optional"/>
            <attribute name="nodeRepresentation" type="tns:LongName" use="optional"/>
        </extension>
    </complexContent>
</complexType>
<element name="Classification" type="tns:ClassificationType" substitutionGroup="tns:Identifiable"/>```

```xml
<complexType name="RegistryObjectType">
    <complexContent>
        <extension base="tns:IdentifiableType">
            <sequence minOccurs="0" maxOccurs="1">
                <element ref="tns:Name" minOccurs="0" maxOccurs="1"/>
                <element ref="tns:Description" minOccurs="0" maxOccurs="1"/>
                <element name="VersionInfo" type="tns:VersionInfoType" minOccurs="0" maxOccurs="1"/>
                <element ref="tns:Classification" minOccurs="0" maxOccurs="unbounded"/>
                <element ref="tns:ExternalIdentifier" minOccurs="0" maxOccurs="unbounded"/>
            </sequence>
            <attribute name="lid" type="anyURI" use="optional"/>
            <attribute name="objectType" type="tns:referenceURI" use="optional"/>
            <attribute name="status" type="tns:referenceURI" use="optional"/>
        </extension>
    </complexContent>
</complexType>
<element name="RegistryObject" type="tns:RegistryObjectType" substitutionGroup="tns:Identifiable"/>
<complexType name="IdentifiableType">
    <annotation>
        <documentation xml:lang="en">
    Common base type for all types that have unique identity.     
    If id is provided and is not in proper URN syntax then it is used for
    linkage within document and is ignored by the registry. In this case the
    registry generates a UUID URN for id attribute.
    id must not be null when object is retrieved from the registry.
    </documentation>
    </annotation>
    <sequence>
        <element ref="tns:Slot" minOccurs="0" maxOccurs="unbounded"/>
    </sequence>
    <attribute name="id" type="anyURI" use="required"/>
    <attribute name="home" type="anyURI" use="optional"/>
    <!-- home attribute is required only for remote ObjectRef -->
</complexType>
<element name="Identifiable" type="tns:IdentifiableType"/>