defmodule Saxon do @moduledoc """ `Saxon` is a highly opinionated XML request parser for `Plug`. It only supports parsing the HTTP requests whose `Content-Type` is `application/vnd.saxon+xml`. The content type that `Saxon` handles is `application/vnd.saxon+xml`. Base64 encoded files can be embedded in the XML at any level. For flat request bodies with file upload, `multipart/form-data` is good. For hierarchical request bodies without embedded files, you should stick to `application/json`. Elixir Rocks 1 2017-03-29T10:23:35Z false (Base64 encoded file content here) Elixir really rocks. (Base64 encoded file content here) Lorem ipsum ... (Base64 encoded file content here) Note the timestamps in the XML must be in `ISO 8601` format **with timezone**. The parser parses such XML and yields %{ "article" => %{ "title" => "Elixir Rocks", "author_id" => 1, "published_at" => %DateTime{year: 2017, month: 3, day: 29, hour: 10, minute: 23, second: 35, time_zone: "Etc/UTC", ...}, "private" => false, "logo" => %Plug.Upload{filename: "logo.png", content_type: "image/png", ...}, "sections" => [ %{ "content" => "Elixir really rocks.", "photo" => %Plug.Upload{filename: "awesome.jpg", content_type: "image/jpeg", ...} }, %{ "content" => "Lorem ipsum ...", "photo" => %Plug.Upload{filename: "cool.png", content_type: "image/png"} } ] } } """ @behaviour Plug.Parsers alias Saxon.{Sax, Reducer} def parse(conn, supertype, subtype, headers, opts \\ []) def parse(conn, "application", "vnd.saxon+xml", _headers, opts) do {result, conn} = Sax.start(conn, Reducer, chunk_size: opts[:saxon_chunk_size]) {:ok, result, conn} end def parse(conn, _, _, _, _) do {:next, conn} end end