# xml.reader

> A module of xml's API.

`xml.reader` — a pull parser over an in-memory XML document.

`XmlReader.next()` hands back one `XmlEvent` at a time: a start tag (with its
attributes), an end tag, a run of text, or end of input. Self-closing tags
produce a start *and* an end event, so a consumer never has to special-case
`<a/>`. Comments, processing instructions, the XML declaration and DOCTYPE are
skipped; CDATA sections come back as text, verbatim.

Entity references are decoded in text and attribute values: the five
predefined ones (`&lt;` `&gt;` `&amp;` `&quot;` `&apos;`) and numeric
character references (`&#65;`, `&#x41;`). Anything else is an error rather
than being passed through, because an API response carrying an undeclared
entity is malformed and silently keeping `&foo;` would hide that.

What this is not: a validating parser. It checks that tags nest and close
with matching names — the property every consumer relies on — and nothing
about DTDs or schemas. Namespaces are left as written (`ec2:item` stays
`ec2:item`); `local_name` strips a prefix when a consumer wants to ignore it.

## Structs

### `Attr`

```mojo
struct Attr
```

One `name="value"` pair, value already entity-decoded.

Implements: `Copyable`, `Movable`

Fields:

- `name: String`
- `value: String`

### `XmlEvent`

```mojo
struct XmlEvent
```

Implements: `Copyable`, `Movable`

Fields:

- `kind: Int`: One of `EVENT_START`, `EVENT_END`, `EVENT_TEXT`, `EVENT_EOF`.
- `name: String`: The tag name for start and end events; empty otherwise.
- `text: String`: The decoded text for text events; empty otherwise.
- `attrs: List[Attr]`: The attributes of a start tag, in document order.

### `XmlReader`

```mojo
struct XmlReader
```

Pull parser over a document held in memory.

The reader owns a copy of the bytes, so the source string may go away.
Call `next()` until it returns an `EVENT_EOF` event; a malformed document
raises with the byte offset where parsing stopped.

Implements: `Movable`

#### `__init__`

```mojo
def __init__(out self, doc: String)
```

#### `depth`

```mojo
def depth(self) -> Int
```

How many elements are open at the current position.

#### `next`

```mojo
def next(mut self) -> XmlEvent
```

## Functions

### `is_blank`

```mojo
def is_blank(s: String) -> Bool
```

True when `s` is only XML whitespace — the indentation between tags.

### `local_name`

```mojo
def local_name(name: String) -> String
```

`ec2:item` → `item`; a name without a prefix is returned unchanged.

### `decode_entities`

```mojo
def decode_entities(raw: Span[UInt8]) -> String
```

Decodes the predefined and numeric entity references in `raw`.

## Aliases

### `EVENT_START`

```mojo
comptime EVENT_START = 1
```

### `EVENT_END`

```mojo
comptime EVENT_END = 2
```

### `EVENT_TEXT`

```mojo
comptime EVENT_TEXT = 3
```

### `EVENT_EOF`

```mojo
comptime EVENT_EOF = 4
```
