goetas-webservices/xsd-reader

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

@goetas pull requests are here, you may have a look to changes, but more tests are coming to ensure those changes are working fine for my use case.