EventReader - Asynchronous XML Parsing
EventReader
Section titled “EventReader”EventReader is the asynchronous stable-event API. It accepts bytes from
a ReadableStream<Uint8Array> or AsyncIterable<Uint8Array> and reads another
input chunk only when the consumer asks for an event that is not already
buffered.
import { EventReader, XmlEventType } from 'stax-xml';
for await (const event of new EventReader(response.body!)) { if (event.type === XmlEventType.START_ELEMENT) { const id = event.attributes.get('id')?.value; console.log(event.name, id); } else if (event.type === XmlEventType.CHARACTERS) { console.log(event.value); }}Every yielded event and attribute is a stable JavaScript object. Advancing the reader does not mutate previously yielded values.
Starting with v1.1, these events can be forwarded directly to
Writer.writeEvent(), with selected events replaced in between. See
XML Transformation Pipelines for complete
sync and async examples.
type StreamReaderSource = | ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>;
interface EventReaderOptions { documentMode?: 'document' | 'fragment'; namespaceAware?: boolean; // default: true autoDecodeEntities?: boolean; // default: true addEntities?: { entity: string; value: string }[]; encoding?: string; // default: 'utf-8'}Byte input is decoded incrementally by a fatal TextDecoder. encoding
defaults to utf-8 and accepts labels supported by the host decoder. The label
is not inferred from the XML declaration. Invalid
byte sequences and malformed XML reject next() and return the underlying
source. The reader does not interpret DTD declarations, resolve external
entities, or perform external I/O.
autoDecodeEntities defaults to true and performs single-pass decoding of
the five predefined XML entities, numeric character references, and trusted
definitions supplied through addEntities. Set it to false to preserve
reference spelling in returned text and attributes while retaining XML
reference validation. CDATA is always literal. Custom definitions are
non-recursive and cannot override predefined entities.
Node.js Readable streams can be passed directly because they are async
iterables and their Buffer chunks are Uint8Array values.
import { createReadStream } from 'node:fs';import { EventReader } from 'stax-xml';
const reader = new EventReader(createReadStream('large.xml'));Lifecycle
Section titled “Lifecycle”EventReader implements both AsyncIterable<AnyXmlEvent> and
AsyncIterator<AnyXmlEvent>. It emits START_DOCUMENT first and
END_DOCUMENT last. Breaking from for await invokes return() and cancels or
returns the source. In a manual loop, call await reader.return() when stopping
early. Concurrent next() calls are rejected.
The first next() may consume input before yielding START_DOCUMENT. BOM, XML
declaration, and DTD preamble information must be inspected before that event
can be materialized, so source errors or cancellation can also occur on the
first call.
Current-Token Alternative
Section titled “Current-Token Alternative”Use StreamReader when reducing event-object allocation matters. It accepts the same
sources and returns the event type while accessors read the current token.
Attribute values can be read by index, qualified name, or the
(namespaceURI, localName) pair.
import { StreamReader, XmlEventType } from 'stax-xml';
const reader = new StreamReader(source);try { while (await reader.next() !== null) { if (reader.eventType() === XmlEventType.START_ELEMENT) { console.log(reader.name(), reader.attributeValue('id')); } }} finally { await reader.close();}Current-token accessors are valid until the next successful next() call.
Event Shapes
Section titled “Event Shapes”AnyXmlEvent covers document, start/end element, characters, CDATA, comment,
processing-instruction, and DTD events. Start-element attributes are an
EventAttributes is a read-only Map keyed by qualified name. Values retain
name, localName, prefix, namespaceURI, and value; iteration follows
source order. JSON.stringify() emits a JSON object rather than {}.
In namespace-aware mode, namespace declarations are included in source order as
attributes in the XMLNS namespace. This lets writeEvent() reproduce the
bindings required by qualified names. attributes is undefined when the
element has none. Start-document events also carry XML declaration metadata,
and start-element events carry selfClosing.
Use the exported type guards such as isStartElement() and isCharacters()
for TypeScript narrowing.
The package does not provide async string input. When the complete XML is
already a JavaScript string, use EventReaderSync or StreamReaderSync so the
string can be scanned directly.