README.md

# Saxon (not released yet!)

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`.

    <map>
      <map name="article">
        <string name="title">Elixir Rocks</string>
        <integer name="author_id">1</integer>
        <timestamp name="published_at">2017-03-29T10:23:35Z</timestamp>
        <boolean name="private">false</boolean>
        <file name="logo" filename="logo.png" content-type="image/png">
          (Base64 encoded file content here)
        </file>
        <list name="sections">
          <map>
            <string name="content">Elixir really rocks.</string>
            <file name="photo" filename="awesome.jpg" content-type="image/jpeg">
              (Base64 encoded file content here)
            </file>
          </map>
          <map>
            <string name="content">Lorem ipsum ...</string>
            <file name="photo" filename="cool.png" content-type="image/png">
              (Base64 encoded file content here)
            </file>
          </map>
        </list>
      </map>
    </map>

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.Conn{filename: "cool.png" content_type: "image/png"}
          }
        ]
      }
    }
    
Currently supported XML elements:

*  `string`
*  `integer`
*  `float`
*  `boolean`
*  `timestamp`, the format of which must be ISO 8601. Timezone is required.
*  `file`, allows attributes `filename` and `content-type`.
*  `list`
*  `map`, all the child elements of which must have a unique `name` attribute.

## Installation

If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `saxon` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [{:saxon, "~> 0.1.0"}]
end
```

_NOT AVAILABLE ON HEX YET!_

## How to use

Just add `Saxon` to the parsers. 
Note that if you have a general XML parser in your parser chain, be sure to add `Saxon` *before* that parser.

    plug Parsers, 
      parsers: [Saxon, :urlencoded, :multipart, :json],
      pass: ["*/*"],
      json_decoder: Poison

Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at [https://hexdocs.pm/saxon](https://hexdocs.pm/saxon).