Reputation: 634
I'm trying to serialize an XML document containing entities to insert into Doctrine MySQL database.
I got, for example, these two attributes in my entity :
The problem is that instead of something like this into my XML doc :
<company>
<id>8888</id>
<name>MyCompany</name>
</company>
I got something like this :
<company id="8888" name="MyCompany"/>
The XML is generated by an independant company I work with ; so I can't change it.
So the Symfony2 serializer is creating an empty $company
attribute :(
Is there a simple way to costumize the seralizing process like I want ? Or do I have to implement a complete independant method ?
Thanks a lot.
Upvotes: 3
Views: 6037
Reputation: 170
Quite old, but I got to a much simpler solution using Serializator
+ xpath
in SerializedName
annotation, so this could be useful for someone.
Having for example this entry XML:
<root>
<company id="123456"/>
</root>
Whe deserializing into an object you could use this annotation to populate the company id into "id" property:
/**
* @Serializer\SerializedName(name="company/@id")
*/
public ?int $id = null;
PS: tested on Symfony 5.4
Upvotes: 0
Reputation: 3426
It's now much easier to serialize XML attributes by using the @SerializeName annotation with '@'.
In your Company entity, when defining $name, add
/**
* @ORM\Column(type="string", length=255)
* @SerializedName('@name')
*/
private $name;
Now when you serialize to XML, it will come out as a property, as expected.
I know the OP was actually asking about deserialization, but hope this helps someone who is searching.
Upvotes: 8
Reputation: 634
Okay so finally I tried to use the JMSSerializerBundle but my case is too complicated. I got many entities with several ManyToOne relations ; and I got bot standard and attributes values in my XML.
So I'll use your idea : create my complete whole Denormalizer. It will use the decoded XML and read it line by line, doing what it has to do (creating entities with Doctrine).
It's gonna be a huge process but the most simple one.
Thank you.
[EDIT] I finally found a pretty good solution. I registered the links between XML and my entity setters into a yaml table
company:
@id: setCompanyId
@name : setCompanyName
address:
@city: setAddressCity
@street: setAddressStreet
...
Thanks to that, I can easily read my whole XML and, for each node/attribute value, find the setter name into the table and then do :
$company = new Company;
$company->setterNameFromTable($value);
Upvotes: 0
Reputation: 7525
I'd create a simple Denormalizer because attributes are already parsed by default XmlEncoder. It adds a special character @
in at the beggining of the key.
Without tweaking alot you could add a context parameter like 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 usage
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));
Which results in
class Company#13 (2) {
protected $id =>
string(4) "8888"
protected $name =>
string(9) "MyCompany"
}
Upvotes: 5