The Marlboro Man
The Marlboro Man

Reputation: 971

Symfony, serialize object with arrays as XML preserving attributes and structure

I am using Symfony2 and trying to serialize different collections of objects into XML. For the sake of brevity, let's assume I am trying to list and unlist entities and this is the XML I want to get as a result:

<?xml version="1.0" encoding="UTF-8"?>
<r someattribute="value">
    <data_list>
        <item id="9" type="a"><![CDATA[list data 1]></item>
        <item id="10" type="a"><![CDATA[list data 2]></item>
        <item id="11" type="b"><![CDATA[list data 3]></item>
    </data_list>
    <data_unlist>
        <uitem id="9" type="a" />
    </data_unlist>
</r>

Here are my classes: Item for the "item" nodes, Uitem for the "uitem" nodes and Model, to contain them all:

class Item
{
    private $data=array();
    public function getData() {return $this->data;}

    public function __construct($id, $type, $value)
    {
        $this->data["@id"]=$id;
        $this->data["@type"]=$type;
        //How do I put $value as the node value????
    }
}

class UItem
{
    private $data=array();
    public function getData() {return $this->data;}

    public function __construct($id, $type)
    {
        $this->data["@id"]=$id;
        $this->data["@type"]=$type;
    }
}

class Model
{
    private $data_list=array();
    private $data_unlist=array();

    public function getDataList() {return $this->data_list;}
    public function getDataUnlist() {return $this->data_unlist;}

    public function __construct()
    {
        $this->data_list[]=new Item(9, 'a', 'list data 1');
        $this->data_list[]=new Item(10, 'a', 'list data 2');
        $this->data_list[]=new Item(11, 'b', 'list data 3');

        $this->data_unlist[]=new UItem(9, 'a');
    }
}

Save for the problem I left commented in the Item class (how to put the node value there) I think that should serialize correctly so...

$model=new Model();
$encoders=array(new XmlEncoder());
$normalizers=array(new GetSetMethodNormalizer());
$serializer=new Serializer($normalizers, $encoders);
$contents_xml=$serializer->serialize($model, 'xml');

This is the result I am getting:

<response>
    <data_list>
        <item id="9" type="a" />
    </data_list>
    <data_list>
        <item id="11" type="b" />
    </data_list>
    <data_unlist>
        <uitem id="9" type="a" />
    </data_unlist>
</response>

As you can see, two separate nodes for "data_list" have been created instead of grouping them into one single node.

Here are my questions:

For the record, I am using the vanilla serializer, no JMS here.

Thanks in advance.

Upvotes: 1

Views: 8233

Answers (2)

Duncanmoo
Duncanmoo

Reputation: 4171

Using Symfony XmlEncoder I am able to build an array and turn it into xml using the encode method. Any array items which are named as @something are turned into attributes of the wrapping element rather than child elements, so:

$encoder = new \Symfony\Component\Serializer\Encoder\XmlEncoder();
$data = [
  'something' => [
    '@foo' => 'bar',
    'yoo' => 'bar',
  ]
];
$xml = $encoder->encode($data, 'xml');

Gives me:

<?xml version="1.0"?>
<response>
  <something foo="bar">
    <yoo>bar</yoo>
  </something>
</response>

Upvotes: 5

Michael Sivolobov
Michael Sivolobov

Reputation: 13240

JMSSerializer was created for these purposes. And I think you should start to use it in your project. It has no overhead and is easy to use.

You can control your serializing options with annotations: http://jmsyst.com/libs/serializer/master/reference/annotations

Upvotes: 1

Related Questions