sabre-io / xml

sabre/xml is an XML library that you may not hate.
http://sabre.io/xml/
BSD 3-Clause "New" or "Revised" License
516 stars 77 forks source link

value-objects across namespaces #97

Closed staabm closed 8 years ago

staabm commented 8 years ago

atm we dont support schemas in which a element has a type from a different namespace, e.g.

<?xml version="1.0" encoding="UTF-8"?>
<!-- store_businessparty_request.xsd -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns="http://clxERP/businessparty"
           targetNamespace="http://clxERP/businessparty"
           xmlns:custom="http://clxERP/businessparty_types"
           elementFormDefault="qualified">

    <xs:import namespace="http://clxERP/businessparty_types" schemaLocation="businessparty_types.xsd"/>

    <xs:element name="store_businessparty_request">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="request_id" type="xs:int"/>
                <xs:element name="business_party" type="custom:businessParty"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>
<?xml version="1.0" encoding="UTF-8"?>
<!-- businessparty_types.xsd -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns="http://clxERP/businessparty_types"
           targetNamespace="http://clxERP/businessparty_types"
           elementFormDefault="qualified">

    <xs:complexType name="businessParty">
        <xs:sequence>
            <xs:element name="sales_agent" type="xs:boolean" default="false" minOccurs="0"/>
            <xs:element name="phone" minOccurs="0">
                <xs:simpleType>
                    <xs:restriction base="xs:string">
                        <xs:maxLength value="50"/>
                    </xs:restriction>
                </xs:simpleType>
            </xs:element>
            <!-- simplified ... -->
        </xs:sequence>
    </xs:complexType>
</xs:schema>

problem is, that our valueObject deserializer atm asumes that the xs:element and its type are within the same package. As you can see here this is not necessarily the case.

example message

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns1:store_businessparty_request
    xmlns:ns1="http://clxERP/businessparty"
    xmlns:ns2="http://clxERP/businessparty_types"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <ns1:request_id>f195525d-b6e5-456a-aee0-e3baa425ac86</ns1:request_id>
    <ns1:business_party>
        <ns2:sales_agent>false</ns2:sales_agent>
        <ns2:phone></ns2:phone>
    </ns1:business_party>
</ns1:store_businessparty_request>

In my use-case I want the store_businessparty_request and the business_party both be de-serialized using the valueObject facilities. In the business_party case my value-object doesnt pick up any values, because it only takes those which are part of the same namespaces as the element itself was defined.

evert commented 8 years ago

I do indeed think that this is a case that falls outside what I want to do with the valueobject stuff. There is after all a pretty good way to deal with these with the elementMappers.

The issue I see is that if we keep on adding functionality that makes that stuff more complex, in the end we either reinvent XSLT or a different domain-specific language that describes parsing. We don't need that, because we can achieve it with PHP code.

staabm commented 8 years ago

I hate my use-cases :/

evert commented 8 years ago

Wouldn't something like this just work:

$service->elementMap['{http://clxERP/businessparty}business-party'] = function($reader) {

   return \Sabre\Xml\Deserializers\valueObject($reader, 'SomeClass', 'http://clxERP/businessparty_types');

});

Gets you 99% there, no? And that's mostly 'configuration'.

staabm commented 8 years ago

hmm this sounds like a good idea... need to check that, thx.

staabm commented 8 years ago

worked for me, thx.