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), )
Values
pub fn attr(e: Element, name: String) -> option.Option(String)
Lookup an attribute by name on an element.
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 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.