콘텐츠로 이동
StAX-XML

StreamReader - 비동기 current-token XML 파싱

StreamReader는 event object를 매 token마다 할당하지 않는 저할당 비동기 XML reader입니다. ReadableStream<Uint8Array> 또는 AsyncIterable<Uint8Array>를 받고 current token을 accessor로 노출합니다.

import { StreamReader, XmlEventType } from 'stax-xml';
const reader = new StreamReader(response.body!);
try {
while (await reader.next() !== null) {
if (reader.eventType() === XmlEventType.START_ELEMENT) {
console.log(reader.name(), reader.attributeValue('id'));
} else if (reader.eventType() === XmlEventType.CHARACTERS) {
console.log(reader.text());
}
}
} finally {
await reader.close();
}

성능과 allocation rate가 stable event object 보존보다 중요할 때 사용하세요. Accessor는 current token만 설명하므로 다음 next() 호출 전에 읽어야 합니다.

type StreamReaderSource =
| ReadableStream<Uint8Array>
| AsyncIterable<Uint8Array>;
interface StreamReaderOptions {
documentMode?: 'document' | 'fragment';
namespaceAware?: boolean; // 기본값: true
autoDecodeEntities?: boolean; // 기본값: true
addEntities?: { entity: string; value: string }[];
encoding?: string; // 기본값: 'utf-8'
}

namespaceAware의 기본값은 true입니다. raw qualified name만 필요하면 false로 설정하세요. namespace URI는 ''가 되고, xmlns 선언은 일반 attribute로 노출되며, 선언되지 않은 prefix도 거부하지 않습니다.

Byte input은 fatal TextDecoder로 incremental decoding합니다. encodingutf-8이 기본이며 host decoder가 지원하는 label을 받을 수 있습니다. XML declaration에서 label을 자동 추론하지 않으므로 byte source와 일치하는 encoding을 지정해야 합니다. 선택한 encoding의 invalid byte sequence, malformed XML, unsupported named entity는 next()를 reject합니다. autoDecodeEntities 기본값은 true이며 predefined, numeric, configured custom entity를 single-pass decode합니다. false이면 validation을 유지하면서 raw reference 표기를 반환합니다. CDATA는 항상 literal입니다. addEntities는 DTD processing 없이 trusted, non-recursive internal definition을 제공합니다. External entity는 resolve하지 않고 외부 I/O도 수행하지 않습니다.

reader는 START_DOCUMENT로 시작하고 END_DOCUMENT로 끝납니다.

reader.eventType();
reader.name();
reader.text();
reader.localName();
reader.prefix();
reader.namespaceURI();
reader.attributeCount();
reader.attributeName(index);
reader.attributeLocalName(index);
reader.attributePrefix(index);
reader.attributeNamespaceURI(index);
reader.attributeValue(indexOrName);
reader.attributeValue(namespaceURI, localName);
reader.namespaceURIForPrefix(prefix);

attributeValue()는 index, qualified name, 또는 (namespaceURI, localName) 쌍을 받습니다. 없는 attribute는 undefined를 반환합니다.

중간에 중단할 때는 await reader.close()를 호출하세요. close는 idempotent이며 underlying async iterator를 닫거나 ReadableStream을 cancel합니다. source error도 reader를 닫은 뒤 원래 error를 다시 throw합니다. Concurrent next() 호출은 reject되므로 이전 호출을 await한 뒤 진행해야 합니다.

stable event object가 필요하면 EventReader를, 완성된 JavaScript string을 동기 처리하려면 StreamReaderSync를 사용하세요.

이 low-allocation model을 유지하며 XML을 변환하려면 각 current token을 대응하는 writer method로 dispatch합니다. Tradeoff와 event 기반 대안은 XML 변환 파이프라인에서 설명합니다.