aws/internal/codec/xml_decode

XML decoder for restXml / awsQuery / ec2Query responses.

The Erlang side (aws_ffi:xml_parse/1) does the heavy lifting via xmerl from the OTP standard library. It returns a Element tree shaped as nested tuples; on the Gleam side we expose that tree and a handful of accessor helpers that the generated decoders call (find_child, find_children, child_text, …).

Whitespace-only text nodes between elements are stripped on the Erlang side so the generated code can address members by element name without thinking about layout. Repeated child elements (used for @xmlFlattened lists) are surfaced by find_children.

Types

Parsed XML element. The first variant is the only one a generated decoder ever sees directly — Text only appears as a child of an element, surfaced via child_text rather than pattern-matched against by callers.

pub type Element {
  Element(
    name: String,
    attrs: List(#(String, String)),
    children: List(Node),
  )
}

Constructors

  • Element(
      name: String,
      attrs: List(#(String, String)),
      children: List(Node),
    )
pub type Node {
  ElementNode(element: Element)
  Text(value: String)
}

Constructors

  • ElementNode(element: Element)
  • Text(value: String)

Tag for the raw Erlang tuple shape coming back from xml_parse. Kept opaque on the Gleam side; converted via node_from_tuple.

pub type RawNode

Values

pub fn attr(e: Element, name: String) -> option.Option(String)

Lookup an attribute by name on an element.

pub fn bool_text(e: Element) -> Result(Bool, String)
pub fn find_child(
  parent: Element,
  name: String,
) -> option.Option(Element)

Find the first child element with the given local name.

pub fn find_children(
  parent: Element,
  name: String,
) -> List(Element)

Find all child elements with the given local name. Used for both @xmlFlattened lists (which appear as repeated siblings of the parent) and for normal wrapped lists (after stepping into the wrapper element).

pub fn float_text(e: Element) -> Result(Float, String)
pub fn inner_list(
  elem: Element,
  member_name: String,
  decode: fn(Element) -> Result(a, String),
) -> Result(List(a), String)

Decode the inner portion of a list element — used for nested lists where the outer caller has already wrapped each entry in <member>...</member> and we need to extract its children as a sub-list. Returns a bare List(a) (not optional) since the surrounding optional_list already gates on presence.

pub fn int_text(e: Element) -> Result(Int, String)
pub fn optional_child(
  parent: Element,
  name: String,
  decode: fn(Element) -> Result(a, String),
) -> Result(option.Option(a), String)

Decode an optional child element if present, otherwise return None. Used in the generated decode_<struct>_xml_inner for member fields.

pub fn optional_flat_list(
  parent: Element,
  name: String,
  decode: fn(Element) -> Result(a, String),
) -> Result(option.Option(List(a)), String)

Decode a flattened list: each entry is a direct child of the parent (no wrapping element). Returns None when there are zero entries, matching the Option(List(a)) shape of normal lists.

pub fn optional_list(
  parent: Element,
  wrapper: String,
  member_name: String,
  decode: fn(Element) -> Result(a, String),
) -> Result(option.Option(List(a)), String)

Decode a wrapped list: <Wrapper><member>v</member>...</Wrapper>. wrapper is the parent name, member_name is the per-entry tag.

pub fn parse(body: String) -> Result(Element, String)

Parse an XML document into an Element. Returns Error("...") on malformed input — generated decoders propagate this up as a DecodeError.

pub fn smithy_float_text(
  e: Element,
) -> Result(json_float.SmithyFloat, String)

Like float_text but recognises the Smithy IEEE-754 special- value tokens (NaN / Infinity / -Infinity) and surfaces them as json_float.SmithyFloat variants. Used by generated Float decoders so the typed output carries the special value rather than failing the entire decode.

pub fn string_text(e: Element) -> Result(String, String)
pub fn text_content(e: Element) -> String

Concatenate all direct text-node children. Used for primitive element values like <Name>foo</Name>.

pub fn timestamp_text(e: Element) -> Result(Int, String)

Decode a Smithy @timestamp element. AWS XML APIs serialise these as ISO 8601 (e.g. 2024-01-02T03:04:05.000Z); our type walker surfaces timestamps as Int (epoch seconds), so we parse the text and convert. Falls back to plain integer parsing for the rare case where the wire form is already epoch seconds.

pub fn timestamp_text_precise(
  e: Element,
) -> Result(json_timestamp.Timestamp, String)

Decode a Smithy @timestamp XML element into the precise Timestamp shape (seconds + nanoseconds). The FFI ISO 8601 parser is currently whole-second precision so nanoseconds will be 0 — once the parser learns fractional seconds we flip that here without breaking the API.

Search Document