Global/Local element partial interpretation of formDefaultElement="unqualified"
Opened this issue · 5 comments
Requests generated by soap-client may have missing namespace prefixes on some elements because of a misinterpretation of formDefaultElement
attribute.
Please read this source about how elementFormDefault
and attributeFormDefault
should be interpreted: https://www.intertech.com/Blog/xml-schema-elementformdefault-and-attributeformdefault
elementFormDefault=”unqualified”
Setting this attribute to “unqualified” means all global elements from this schema must be qualified, and all local elements must be unqualified, when used in an XML document.
This article makes a difference between Global and Local elements, but it seems this library doesn't implement this difference.
Here's the WSDL that cause the issue: https://afis.id3.eu/BiometricIdServices/Id3BiometricIdServicePort?wsdl
It's related to an XSD using elementFormDefault="unqualified" here:
http://afis.id3.eu/BiometricIdServices/Id3BiometricIdServicePort?xsd=Id3BiometricIdService_schema5.xsd
With this WSDL, when invoking IdentifySubject action, the generated request is missing the namespace on IdentifySubjectRequest
node, causing a SOAP Fault from the server.
<?xml version="1.0" encoding="UTF-8"?>
<SOAP:Envelope xmlns:SOAP="http://www.w3.org/2003/05/soap-envelope">
<SOAP:Body>
<ns-4c7934d9:IdentifySubject xmlns:ns-4c7934d9="http://biometricid.id3.eu/">
<IdentifySubjectRequest>
<data>
<FingerDataRecord>
...
</FingerDataRecord>
</data>
</IdentifySubjectRequest>
</ns-4c7934d9:IdentifySubject>
</SOAP:Body>
</SOAP:Envelope>
According to the Blog article, as elementFormDefault
is set to unqualified in related XSD and IdentifySubjectRequest is a Global element inside the XSD, it should be prefixed.
When importing this WSDL in SoapUI, generated requests are valid with the namespace prefix on IdentifySubjectRequest
and SoapUI can consume the web service properly.
I think this issue belongs to xsd-reader more than xsd2php, because xsd-reader could provide the global/local information on parsed elements, so that xsd2php can use this information to generate JMS mapping properly.
Hi,
thanks for providing such detailed description of the issue. I wasn't aware of such subtle difference.
So you are saying that it should be :
<?xml version="1.0" encoding="UTF-8"?>
<SOAP:Envelope xmlns:SOAP="http://www.w3.org/2003/05/soap-envelope">
<SOAP:Body>
<ns-4c7934d9:IdentifySubject xmlns:ns-4c7934d9="http://biometricid.id3.eu/">
<IdentifySubjectRequest xmlns="http://biometricid.id3.eu/">
<data>
<FingerDataRecord>
...
</FingerDataRecord>
</data>
</IdentifySubjectRequest>
</ns-4c7934d9:IdentifySubject>
</SOAP:Body>
</SOAP:Envelope>
Right?
With <IdentifySubjectRequest xmlns="http://biometricid.id3.eu/">
...
As the namespace prefix is declared on IdentifySubject node, IdentifySubjectRequest should be prefixed too, so it should be the following:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP:Envelope xmlns:SOAP="http://www.w3.org/2003/05/soap-envelope">
<SOAP:Body>
<ns-4c7934d9:IdentifySubject xmlns:ns-4c7934d9="http://biometricid.id3.eu/">
<ns-4c7934d9:IdentifySubjectRequest">
<data>
<FingerDataRecord>
...
</FingerDataRecord>
</data>
</ns-4c7934d9:IdentifySubjectRequest>
</ns-4c7934d9:IdentifySubject>
</SOAP:Body>
</SOAP:Envelope>
I have tried with your envelope and it fails.
I have spent 3 days trying to workaround this issue and finally found this article clearly explaining the expected behavior 😭. SOAP ...
I have forked xsd-reader
and xsd2php
to implement this subtle thing, i'll let you know when it's ready and open pull requests.
Links to required pull requests for this to work properly (This also include small changes to support Symfony 4/5)
@goetas I'm still alive :)
I struggle to configure a local development environment with all required goetas-webservices/*
dependencies ... How do you configure your local dev environment that may involve changes in many modules at the same time ?
Here, it seems xsd-reader, xsd2php and soap-client needs some changes, but it's not easy to configure composer so symlinks are used on each projects.
I install the libraries using composer - - prefer-source, that will clone all the repos, then i create a new branch with phpstorm, that will create the same branche name for all the projects in vendor. When pushing the changes, phpstorm will try also to push them all.
Then of course you need to open the related pull request on github