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

  1. The two pieces that make this work are registering :xml in the controller's formats list and setting put_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.