XML Rest output without <response> root node

Created on 18 November 2024, 2 days ago

I'm trying to create a REST endpoint, returning arbitrary XML with my own custom document root.

Much like my JSON endoints, I tried using ResourceResponse, which works ALMOST perfectly for XML.

If I create a REST endpoint, tell it to return XML, and ask it to return the result of:

$response = new ResourceResponse([
        "foo" => [
          "bar" => "baz",
          "@hello" => "zoo"
        ]
      ], 200);

I get the following in response:

<?xml version="1.0"?>
<response>
    <foo hello="zoo">
        <bar>baz</bar>
    </foo>
</response>

Very close! The problem is that tag. I want my own custom xml root.

Digging deep into the code, the fault appears to be in ResourceResponseSubscriber::renderResponseBody():

      $serialization_context = [
        'request' => $request,
        CacheableNormalizerInterface::SERIALIZATION_CONTEXT_CACHEABILITY => new CacheableMetadata(),
      ];

      $output = $serializer->serialize($data, $format, $serialization_context);

That $serialization_context gets passed all the way down to vendor/symfony/serializer/Encoder/XmlEncoder.php and would allow me to change the $xmlRootNodeName. But it's hard coded, and I have no way of modifying it.

Now, this is an event subscriber and I've seen a few people suggesting writing their own EventSubscriber, basically creating a new "xml" format which handles the root XML differently. But that feels like it's complete overkill.

Is there some better way of building an XML document as an endpoint? I know I can just render it as a string, but that also seems like a real waste.

A trivial solution might be to make a patch to ResourceResponse and ResourceResponseSubscriber to pass additional context, but I don't want to go this direction if there's a cleaner solution.

💬 Support request
Status

Active

Version

11.0 🔥

Component

rest.module

Created by

🇨🇦Canada TrevorBradley

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @TrevorBradley
  • 🇨🇦Canada TrevorBradley

    For example, this trivial patch would allow additional context to be passed down to the XmlEncoder, and now a simple call to:

    $response = new ResourceResponse($response, $response_code, [], ['xml_root_node_name' => 'myroot']);

    allows me to put in my own arbitrary root node.

    I'm not proposing this as a solution, just trying to understand the problem. Why is the definition of the $serialization_context in ResourceResponseSubscriber so rigid?

  • 🇳🇿New Zealand quietone

    Changes are made on on 11.x (our main development branch) first, and are then back ported as needed according to our policies.

Production build 0.71.5 2024