У меня проблема с десериализацией и XML в Symfony. Я попробовал обычный сериализатор Symfony, но и там он не работает.
Насколько я вижу, все вроде правильно, но я не вижу проблемы.
Контроллер:
<?php
namespace App\Controller;
use App\DataObjects\Dossiers;
use JMS\Serializer\SerializerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
#[Route('/test')]
class TestController extends AbstractController
{
private $serializer;
public function __construct(SerializerInterface $serializer)
{
$this->serializer = $serializer;
}
#[Route('/')]
public function test(): Response
{
$xmlContent = '<?xml version = "1.0" encoding = "UTF-8" standalone = "yes"?>
<Dossiers source = "Source" type = "myType">
<Dossier>
<Name>Name</Name>
<Description>Description</Description>
</Dossier>
</Dossiers>';
// Deserialisieren Sie den XML-Inhalt
$dossiers = $this->serializer->deserialize($xmlContent, Dossiers::class, 'xml');
// Debugging
echo "Source: " . $dossiers->getSource() . "<br>";
echo "Type: " . $dossiers->getType() . "<br>";
echo "Dossiers:<br>";
foreach ($dossiers->getDossiers() as $dossier) {
echo " Name: " . $dossier->getName() . "<br>";
echo " Description: " . $dossier->getDescription() . "<br>";
}
dd($dossiers);
return new Response('Parsed XML');
}
}
Приложение\DataObjects\Досье:
<?php
namespace App\DataObjects;
use JMS\Serializer\Annotation as JMS;
/**
* @JMS\XmlRoot("Dossiers")
*/
class Dossiers
{
/**
* @JMS\XmlAttribute
* @JMS\SerializedName("source")
* @JMS\Type("string")
*/
private $source;
/**
* @JMS\XmlAttribute
* @JMS\SerializedName("type")
* @JMS\Type("string")
*/
private $type;
/**
* @JMS\SerializedName("Dossier")
* @JMS\Type("array<App\DataObjects\Dossier>")
* @JMS\XmlList(inline = true, entry = "Dossier")
*/
private $dossiers = [];
public function getSource()
{
return $this->source;
}
public function setSource($source)
{
$this->source = $source;
}
public function getType()
{
return $this->type;
}
public function setType($type)
{
$this->type = $type;
}
public function getDossiers()
{
return $this->dossiers;
}
public function setDossiers(array $dossiers)
{
$this->dossiers = $dossiers;
}
}
Приложение\DataObjects\Досье:
<?php
namespace App\DataObjects;
use JMS\Serializer\Annotation as JMS;
class Dossier
{
/**
* @JMS\XmlElement(cdata=false)
* @JMS\SerializedName("Name")
* @JMS\Type("string")
*/
private $name;
/**
* @JMS\XmlElement(cdata=false)
* @JMS\SerializedName("Description")
* @JMS\Type("string")
*/
private $description;
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
public function getDescription()
{
return $this->description;
}
public function setDescription($description)
{
$this->description = $description;
}
}
Возврат на данный момент:
Source:
Type:
Dossiers:
App\DataObjects\Dossiers {#146 ▼
-source: null
-type: null
-dossiers: []
}
Я хочу, чтобы XML был помещен в DataObjects, чтобы я мог использовать DataObject позже для более сложных задач.
Ой, извини. На самом деле происходит то, что я ничего не получаю обратно. Возвращаемое значение для приведенного выше кода в Symfony 7 следующее: Источник: Тип: Досье: App\DataObjects\Dossiers {#146 ▼ -source: null -type: null -dossiers: [] }
Пробовали ли вы сериализовать, чтобы дважды проверить структуру совпадений xml? Я думаю, может, нужно завернуть предметы в поле? <Dossiers ... ><dossiers><Dossier></...>
XML не создан мной, а предоставлен мне, и я не могу ничего изменить в структуре XML. Это <Досье ...><Досье></Досье></Досье> Я бы даже не стал создавать эту структуру, поскольку Досье всегда одно.
Хорошо, я нашел несколько подходящих примеров, но это (обратный пример теста) будет способом проверить, что все настроено правильно.
Кажется, у нас здесь что-то есть. $testDossiers = новые досье('TestSource', 'TestType', новое досье('TestName')); создает: <?xml version = "1.0"coding = "UTF-8"?> <result source = "TestSource" type = "TestType"> <Name><![CDATA[TestName]]></Name> </ result> Что выглядит как-то неправильно.






Я нашел проблему.
Сериализатор JMS дает вам немного больше аннотаций, чем я использовал. Поэтому я добавил XmlRoot и XmlNamespace в начале первого класса, чтобы правильно обрабатывать весь XML. теперь это работает.
<?xml version = "1.0" encoding = "UTF-8" standalone = "yes"?>
<atom:Dossiers xmlns:atom = "http://www.w3.org/2005/Atom" source = "TestSource" type = "TestType">
<atom:Dossier>
<atom:Name>Name</atom:Name>
#[JMS\XmlRoot("Dossiers")]
#[JMS\XmlNamespace(uri:"http://www.w3.org/2005/Atom", prefix:"atom")]
class Dossiers
{
/**
* @JMS\XmlAttribute
* @JMS\SerializedName("source")
* @JMS\Type("string")
*/
private $source;
/**
* @JMS\XmlAttribute
* @JMS\SerializedName("type")
* @JMS\Type("string")
*/
private $type;
/**
* @JMS\SerializedName("Dossier")
* @JMS\Type("App\DataObjects\Dossier")
* @JMS\XmlElement(cdata=false, namespace = "http://www.w3.org/2005/Atom")
*/
Ваши пользовательские теги XML не являются допустимыми для ATOM. Я предлагаю вам использовать собственное пространство имен (uri) и префикс.
Я использую свой собственный, просто изменил его на Atom, чтобы сделать его анонимным.
Вы показали нам код и рассказали, какова ваша цель, но вы не рассказали нам, в чем на самом деле заключается «проблема», с которой вы столкнулись. Что происходит, когда вы посещаете маршрут
'/test/'?