2015-01-05 4 views
2

Я пытаюсь сериализовать XML-документ, содержащий объекты для вставки в базу данных Doctrine MySQL.Сериализовать XML-документ с атрибутами

я, к примеру, эти два атрибута в моей сущности:

  • $ CompanyID
  • $ COMPANYNAME

Проблема заключается в том, что вместо того, чтобы что-то вроде этого в моем XML документ:

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

я получил что-то вроде этого:

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

XML создан независимой компанией, с которой я работаю; поэтому я не могу его изменить. Так сериализатору Symfony2 создает пустой $company атрибут :(

есть простой способ costumize процесс seralizing, как я хочу? Или я должен реализовать полный метод?

самостоятельный

Спасибо большое.

ответ

3

Я бы создать простой Denormalizer, поскольку атрибуты уже разобраны по умолчанию XmlEncoder. Это придает особый характер @ в на самом начале ключа.

Без тонкой настройки много вы могли объявление d параметр контекста, такой как use_attributes, который может понять ваш пользовательский денормализатор. Вот пример

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); 
    } 
} 

А вот пример использования

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)); 

Какие результаты в

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

Хорошо, я понял.Но это немного сложнее, потому что я могу иметь несколько '' в том же файле XML, и мне также нужно управлять отношениями ... Думаю, мне придется использовать JMSSerializerBundle! –

+0

[** jms/serializer **] (https://github.com/schmittjoh/serializer) действительно является хорошей альтернативой для более сложных случаев (массив объектов, глубокая сериализация ...). Однако управлять простым массивом объектов можно легко с помощью приведенного примера. – Touki

+0

Да, спасибо большое за ваш пример; Я пытаюсь несколько решений, я дам вам знать, какой из них был лучшим. –

0

Хорошо, так в конце концов я попытался использовать JMSSerializerBundle, но мой случай слишком сложен. У меня много организаций с несколькими отношениями ManyToOne; и я получил стандартную боту и атрибуты значений в моем XML.

Итак, я воспользуюсь вашей идеей: создайте мой полный Denormalizer. Он будет использовать декодированный XML и читать его по строкам, делая то, что он должен делать (создание объектов с Doctrine).

Это будет огромный процесс, но самый простой.

спасибо.

[EDIT] Я, наконец, нашел довольно хорошее решение. Я зарегистрировал связь между XML и моими сущностями сеттеров в таблицу YAML

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

Благодаря этому, я могу легко прочитать весь мой XML и для каждого значения узла/атрибута, найти сеттер имя в таблицу и затем выполните:

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