schmittjoh / serializer

Library for (de-)serializing data of any complexity (supports JSON, and XML)
http://jmsyst.com/libs/serializer
MIT License
2.32k stars 589 forks source link

A DOM Visitor #168

Open ElectricMaxxx opened 10 years ago

ElectricMaxxx commented 10 years ago

Cause i had a lot of trouble with parsing more advanced xml strings, i started to create a DOM-Visitor, wich handle all stuff by using the php DOM classes instead of the SimpleXMLElement thing.

Before i do a PR i want to know if somebody will find it as useful as i do?

The mapping class for the formats needs to be changed, too.

I think with this way we are able to solve more advanced stuff (namespaces, xsd,...) in an easier way.

You could see the changes in my fork: https://github.com/ElectricMaxxx/serializer

I will try to do these things too:

schmittjoh commented 10 years ago

Could you elaborate what trouble you had?

Adding a new visitor is a lot of work and will also require all userland code (handlers/listeners) to implement support for such a new visitor.

ElectricMaxxx commented 10 years ago

i got a lot of empty strings while trying to deserialize a a soap-answer.

i saw the reasion in the parsing with simpleXML. I tried to parse the string with simpleXML (without JMSSerializer), i got the xpath to node by adding namespaces but getting empty strings, too. The strings where not empty they where new SimpleXMLElenet objects. I thing SimpleXML doesn`t recognize them as strings. The Deserializer generates the object structure but could fill my properties like the pure simpleXML.

Here is an Example (do it only the deserialize way):

namespace TeleCashPaymentBundle\models\Soap;
use JMS\Serializer\Annotation as JMS;

class SoapResponseBody {
    /**
     * @JMS\Type("TeleCashPaymentBundle\models\Soap\SoapFault")
     * @JMS\XmlValue
     */
    public $Fault;

    /**
     * @JMS\Type("TeleCashPaymentBundle\models\Soap\TelecashOrderResponse")
     * @JMS\XmlValue
     */
    public $IPGApiOrderResponse;

}

and the class for a level deeper:

namespace TeleCashPaymentBundle\models\Soap;
use JMS\Serializer\Annotation as JMS;

class SoapFault {
    /**
     * an telecash own code
     *
     * @JMS\Type("string")
     * @JMS\XmlValue
     */
    public $faultcode;

    /**
     * the string with the fault
     *
     * @JMS\Type("string")
     * @JMS\XmlValue
     */
    public $faultstring;

    /**
     * detailed information of the fault
     *
     * @JMS\Type("string")
     * @JMS\XmlValue
     */
    public $detail;

    /**
     * @JMS\Type("TeleCashPaymentBundle\models\Soap\TelecashOrderResponse")
     * @JMS\XmlValue
     */
    public $IPGApiOrderResponse;
}

i only wanted to get the strings in the fault class. For Serialization i would need some @xmlRoot, but wanted to deserialize in the first step.

But now, when i use the DOMDocument stuff i got a all. I try to get all tests green at the moment, to get the same behavior like the "normal xml" visitor.

Cause i need it i would try to end it fit it to your system. I would write some more documentation, too :-)

ElectricMaxxx commented 10 years ago

Would it be a solution to completly replace the XmlDeserializer with a new one. (for your handlers/listeners), if i try to keep the interface equal?

ElectricMaxxx commented 10 years ago

Hi,

i thought i can create my dom visitor faster. All simple visitor methods are done are tested and work fine. But I have got problems with the setting of values of classes where the value needs to be injected in the constructor. Could you (@schmittjoh) give me a little hint how you have done it for the simple XmlDeserializationVisitor? first issue i have ist: the object is constructed before somebody ask the xml if the is a matching property second issue: the object (or its class) has no property with annotations that declare the behavior and fill the property metadata -> the loop for visiting the node won`t be visisted -> no data example: DateTime object I got the same issue, when i have a class with private properties, where the property has to be injected to the constructor.

I thing the former tests for that in the XmlDeserializationVisitor had been green, but how? My changes in the GraphNavigator (do some refactoring) are doing the same.

ElectricMaxxx commented 10 years ago

Or could those things only be done by adding a strategy?

ElectricMaxxx commented 10 years ago

Now i know what you ment with your concern about changing handlers and so on. Now i understand it better :-)

But i managed following things: -> refactoring of the GraphNavigator::accept() -> the section with the objects handling -> updated the handlers (Date,ArrayCollection,PhpCollection) -> solved almost all tests

i have got only 11 red ones, and some skiped ones -> will make these ones green today

If you will have a look in my fork: be carefull cause it seems that i have changed all - fuck Windows-LineEndings, will replace it with a new fork and the changes i realy made.

proggeler commented 3 years ago

@ElectricMaxxx I had some issues (de)serializing soap requests too. I've created a SoapSerializer for this: dmt-software/jms-soap-serializer. Maybe it can help your soap implementation(s) too?