You need to enable JavaScript to run this app. 如何通过Symfony Serializer自定义生成符合Atom结构的XML文件
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Symfony Serializer自定义生成符合Atom结构的XML文件

实现方法

完全不需要自定义XmlEncoder,靠Symfony Serializer原生的数组映射规则+序列化上下文参数,就能100%自定义任意XML结构,不用改动编码器源码。

你当前代码的几个可修正的问题

  • 初始化XmlEncoder时传入的根节点名result和序列化上下文里的xml_root_node_name参数重复,上下文参数优先级更高,初始化时的参数可以省略
  • 你之前定义的带@xmlns、#的$tag数组完全没有被传入序列化流程,是无效代码
  • 现有默认输出和目标结构的差异,本质都是数据结构和渲染规则不匹配,不需要改编码器就能解决:
    • 根节点<feed>需要带命名空间属性
    • 根节点下需要加固定的<logo>节点
    • 原有的<item>标签替换为<entry>,去掉自动生成的key="0"这类冗余索引属性
    • 原有的多层嵌套节点(比如header > title、module > date > time)拆平到<entry>的直接子节点,同时把subtitle改名为notsubtitle、时间节点改名为created
    • 原有的body.html内容放到带type="xhtml"属性的<content>节点下,嵌套<div>标签包裹
    • 不需要的location等字段直接过滤掉即可

具体实现代码

public function servicesXml(ContentRepository $content): Response
{
    // 实际项目中直接使用框架自动注入的Serializer服务即可,无需手动实例化
    $encoder = [new XmlEncoder()];
    $normalizer = [new ObjectNormalizer()];
    $serializer = new Serializer($normalizer, $encoder);

    $contents = $content->getContents();

    // 先把数据库查询结果整理成和目标XML完全一一对应的关联数组
    $feedData = [
        // @开头的key会被识别为标签属性
        '@xmlns' => 'http://www.w3.org/2005/Atom',
        // 固定的logo节点值替换成实际地址
        'logo' => 'https://你的域名/logo.png',
        // 把每条内容映射为entry节点
        'entry' => array_map(function(Content $item) {
            return [
                'id' => $item->getId(),
                'title' => $item->getHeader()->getTitle(),
                'notsubtitle' => $item->getHeader()->getSubtitle(),
                'created' => $item->getHeader()->getModule()->getDate()->getTime(),
                'author' => [
                    'name' => $item->getHeader()->getAuthor()->getName()
                ],
                'content' => [
                    // content节点的属性
                    '@type' => 'xhtml',
                    // 嵌套div包裹html内容,编码器会自动处理特殊字符转义/CDATA
                    'div' => $item->getBody()->getHtml()
                ]
            ];
        }, $contents)
    ];

    $xmlOutput = $serializer->serialize($feedData, 'xml', [
        'xml_format_output' => true,
        'xml_encoding' => 'utf-8',
        'xml_root_node_name' => 'feed',
        // 去掉数组索引自动生成的key属性,消除类似<item key="0">的冗余输出
        'xml_keep_array_node' => false,
        'remove_empty_tags' => true
    ]);

    return new Response($xmlOutput, 200, ['Content-Type' => 'application/xml']);
}

关键的原生支持规则(不用改编码器就能用)

很多开发者遇到自定义结构需求第一反应是重写编码器方法,其实完全没必要——XmlEncoder对关联数组的特殊语法支持已经覆盖了99%的自定义XML结构场景,自定义编码器只适合需要做XML校验、自定义节点逻辑的极端场景。常用的原生规则包括:

  • 数组中以@开头的key,会自动渲染为所在标签的属性,比如'@type' => 'xhtml'最终会生成<content type="xhtml">
  • 数组中以#开头的key,会作为所在标签的纯文本值,XmlEncoder会自动处理特殊字符、CDATA转义,不需要手动拼接标签
  • 不需要输出的字段,只要在数组映射环节不加入即可,比在Normalizer里配置忽略属性灵活很多

注意:你目标结构里写的xlns是拼写笔误,W3C XML规范里命名空间属性是xmlns,拼写错误会导致命名空间失效。


内容的提问来源于stack exchange,提问作者Menryck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.09 15:24:08