Packages

Find Brazilian addresses by postal code, directly from Correios API. No HTML parsers.

Current section

Files

Jump to
correios_cep lib correios cep parser.ex
Raw

lib/correios/cep/parser.ex

defmodule Correios.CEP.Parser do
@moduledoc """
Parser for Correios API responses.
"""
import SweetXml, only: [sigil_x: 2, xpath: 2, xpath: 3]
alias Correios.CEP.{Address, Error}
@address_map [
street: "end",
complement: "complemento",
complement2: "complemento2",
neighborhood: "bairro",
city: "cidade",
state: "uf",
postal_code: "cep"
]
@xmap_params for {new_key, old_key} <- @address_map,
into: [],
do: {new_key, ~x"./#{old_key}/text()"}
@doc """
Parses a successful Correios API response body to `#{inspect(Address)}` struct.
When the response body is empty, returns a not found `#{inspect(Error)}` struct.
## Examples
iex> #{inspect(__MODULE__)}.parse_ok(response_body)
%#{inspect(Address)}{ ... }
iex> #{inspect(__MODULE__)}.parse_ok(response_body)
%#{inspect(Error)}{reason: "CEP NAO ENCONTRADO"}
"""
@spec parse_ok(String.t()) :: Address.t() | Error.t()
def parse_ok(response) when is_binary(response) do
response
|> xpath(~x"//return"o, @xmap_params)
|> build_response()
end
@spec build_response(map() | nil) :: Address.t() | Error.t()
defp build_response(nil), do: Error.new("CEP NAO ENCONTRADO")
defp build_response(response) when is_map(response), do: Address.new(response)
@doc """
Parses a Correios API response error to `#{inspect(Error)}` struct.
## Examples
iex> #{inspect(__MODULE__)}.parse_error(response_body)
%#{inspect(Error)}{ ... }
iex> #{inspect(__MODULE__)}.parse_error(:timeout)
%#{inspect(Error)}{reason: "timeout"}
"""
@spec parse_error(any()) :: Error.t()
def parse_error(response) when is_binary(response) do
response
|> xpath(~x"//faultstring/text()")
|> Error.new()
end
def parse_error(response), do: Error.new(response)
end