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], # add :xml here
        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 AmblogWeb, :html

   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.