Adding XML support in Phoenix 1.7
It wasn't so obvious how to render XML in Phoenix with the new approach to live views and rendering of templates. This is quick guide on how to do so. This could be wrong at the moment of reading this but always refer to the internet.
Introduction
In this post, I'll guide you through the process of adding XML support to a Phoenix 1.7+ project. This is a consolidation of various forum insights, tailored for quick reference. Note that some details may become outdated, so always refer to the latest Phoenix documentation for updates.
Modifying the Web Module
First, update the FooWeb module to include XML in the list of supported formats:
#/lib/foo_web.ex
defmodule FooWeb do
# .. omit for clarity
def controller do
quote do
use Phoenix.Controller,
formats: [:html, :json, :xml], # [!code highlight]
layouts: [html: FooWeb.Layouts]
import Plug.Conn
import FooWeb.Gettext
unquote(verified_routes())
end
end
# .. omit for clarity
end
Creating the controller
Next, create an RSS controller to handle XML responses:
# /lib/foo_web/controllers/rss_controller.ex
defmodule FooWeb.RSSController do
use FooWeb, :controller
plug :put_layout, false
def index(conn, _params) do
conn
|> put_resp_content_type("application/rss+xml")
|> render("rss.xml", posts: ["a", "b", "c"])
end
end
Setting Up the View
Set up a view to render the XML content:
# /lib/foo_web/controllers/rss_xml.ex
defmodule FooWeb.RSSXML do
use FooWeb, :html # [!code highlight]
embed_templates "rss_xml/*"
end
Creating the template
Create an XML template for the RSS feed:
# /lib/foo_web/controllers/rss_xml/rss.xml.eex
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
#.. omit for clarity. You put whatever XML tags you need here
</channel>
</rss>
Updating the Router
Finally, update the router to direct requests to the RSS controller:
# lib/foo_web/router.ex
get "/rss.xml", RSSController, :index
Restart your server and try it out.1
-
The two pieces that make this work are registering
:xmlin the controller'sformatslist and settingput_resp_content_type("application/rss+xml")in the action — without the content type, browsers and feed readers will treat the response as plain text rather than a feed. ↩