Serializing an XML Document with Attributes

I am trying to serialize an XML document containing entities for insertion into a Doctrine MySQL database.

I got for example these two attributes in my entity:

  • $ CompanyID
  • $ COMPANYNAME

The problem is that instead, in my XML document:

<company>
    <id>8888</id>
    <name>MyCompany</name>
</company>

      

I have something like this:

<company id="8888" name="MyCompany"/>

      

XML is created by an independent company I work with; so I cannot change it. Therefore Symfony2 serializer creates an empty attribute $company

(

Is there an easy way to get the seralization process the way I want? Or do I need to implement a complete independent method?

Many thanks.

+3


source to share


2 answers


I would create a simple Denormalizer since the attributes are already parsed by the default XmlEncoder . He adds a special character @

at the start of the game.

Without customization, you can add a context parameter, for example use_attributes

, which your custom denormalizer can understand. Here's an example

use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;

class AttributesDenormalizer implements DenormalizerInterface
{
    public function __construct(DenormalizerInterface $delegate)
    {
        $this->delegate = $delegate;
    }

    public function denormalize($data, $class, $format = null, array $context = array())
    {
        if (!is_array($data) || !isset($context['use_attributes']) || true !== $context['use_attributes']) {
            return $this->delegate->denormalize($data, $class, $format, $context);
        }

        $attributes = array();

        foreach ($data as $key => $value) {
            if (0 === strpos($key, '@')) {
                $attributes[substr($key, 1)] = $value;
            }
        }

        if (empty($attributes)) {
            $attributes = $data;
        }

        return $this->delegate->denormalize($attributes, $class, $format, $context);
    }

    public function supportsDenormalization($data, $type, $format = null)
    {
        return $this->delegate->supportsDenormalization($data, $type, $format);
    }
}

      

And here is an example of use



use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;

$xml = '<company id="8888" name="MyCompany"/>';

$encoders = array(new XmlEncoder());
$normalizers = array(new AttributesDenormalizer(new GetSetMethodNormalizer));

$serializer = new Serializer($normalizers, $encoders);
$serializer->deserialize($xml, 'Company', 'xml', array('use_attributes' => true));

      

The result is

class Company#13 (2) {
  protected $id =>
  string(4) "8888"
  protected $name =>
  string(9) "MyCompany"
}

      

+4


source


Ok, finally I tried to use JMSSerializerBundle but my case is too complicated. I have many organizations with multiple ManyToOne relationships; and I got the default bot and value attributes in my XML.

So, I'll use your idea: create my complete Denormalizer. It will use the decoded XML and read it line by line, doing what it is supposed to do (creating objects with Doctrine).

It will be a huge process, but the easiest one.

Thank.



[EDIT] I finally found a pretty good solution. I have registered the links between XML and my object setters into the yaml table.

company:
    @id: setCompanyId
    @name : setCompanyName
    address:
        @city: setAddressCity
        @street: setAddressStreet
...

      

Thanks to this, I can easily read my entire XML and, for each node / attribute value, find the setter name in the table and then do:

$company = new Company;
$company->setterNameFromTable($value);

      

0


source







All Articles