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.
source to share
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"
}
source to share
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);
source to share