StAX-XML: JavaScript/TypeScript के लिए हाई-परफॉर्मेंस स्ट्रीमिंग XML parser
(github.com/Clickin)मेरे कार्यस्थल पर Java में बना एक legacy service है जो XML-आधारित संचार करता है। legacy service को backend में रखते हुए जब मैंने js-आधारित web service नई बनानी चाही, तो मुझे ठीक वैसा XML parser नहीं मिला जैसा मैं चाहता था, इसलिए मैंने खुद ही बना लिया।
यह StAX-आधारित pull तरीके से XML को parse करता है और asynchronous implementation देता है, इसलिए Stream-आधारित बड़े XML files को भी लगभग 10MB memory में parse किया जा सकता है.
ECMAScript standard में string की अधिकतम लंबाई 2^53 - 1 होने के कारण 1GB से बड़े XML के लिए अब तक SAX parser का उपयोग करना पड़ता था, लेकिन मुझे लगता है कि यह library एक अच्छा विकल्प बन सकती है।
काम में मैं मुख्य रूप से Java इस्तेमाल करता हूँ और Node ecosystem के लिए library बनाना मेरे लिए पहली बार है, इसलिए अगर कहीं कमी हो तो सुझाव दें, मैं उन्हें यथासंभव शामिल करने की कोशिश करूँगा।
इतिहास
शुरुआत में मैंने सोचा था कि Java की woodstox library को wasm से bind करके इस्तेमाल करूँ,
लेकिन उस समय wasm में अभी GC implementation नहीं था, इसलिए मुझे लगा कि Java को wasm में compile करना अभी समय से पहले होगा, और मैंने वह विचार छोड़ दिया।
दूसरे प्रयास में मैंने Rust की quick-xml को wasm से bind करके देखा, लेकिन stream को wasm में भेजकर process करने की लागत बहुत ज़्यादा थी, और मौजूदा JavaScript XML parser की तुलना में performance का अंतर बहुत बड़ा हो गया, इसलिए उसे भी drop कर दिया।
अंत में मैंने pure TypeScript में लिखने का निर्णय लिया और कई AI की मदद लेते हुए V8 engine target के लिए कई optimizations भी लागू किए।
🚀 मुख्य विशेषताएँ
पूरी तरह asynchronous stream-आधारित parsing
- बड़े XML files (सैकड़ों MB~GB) को memory-efficient तरीके से process करना
- ReadableStream आधारित real-time parsing, बिना main thread को block किए
- pull तरीके से जितना चाहिए उतना ही data process करना
// 970MB file को भी 10MB से कम memory में process किया जा सकता है
const parser = new StaxXmlParser(largeXmlStream);
for await (const event of parser) {
// streaming के साथ event process करना
}
StAX-style event-आधारित parsing
यह Java developers के लिए परिचित pull parser pattern प्रदान करता है, जिससे XML structure पर बारीक नियंत्रण किया जा सकता है।
import { StaxXmlParser, isStartElement, isCharacters } from 'stax-xml';
for await (const event of parser) {
if (isStartElement(event)) {
console.log(`tatva: ${event.name}`, event.attributes);
} else if (isCharacters(event)) {
console.log(`text: ${event.value}`);
}
}
🛠️ 4 मुख्य components
1. StaxXmlParser (asynchronous parser)
- बड़ी files के लिए: stream-आधारित memory-efficient parsing
- real-time processing: fetch API के साथ remote XML को real-time में parse करना
- TypeScript type guards: runtime type safety की गारंटी
2. StaxXmlParserSync (synchronous parser)
- छोटी files के लिए optimized: in-memory XML string की high-speed parsing
- web API responses: synchronous workflow में तुरंत processing
3. StaxXmlWriter (asynchronous writer)
- streaming generation: सीधे WritableStream में XML output
- real-time response: API server में बड़े XML responses generate करना
- memory-efficient: पूरे XML को memory में store नहीं करता
4. StaxXmlWriterSync (synchronous writer)
- तुरंत generation: memory के भीतर XML string build करना
- web server integration: Express, Hono आदि के साथ पूर्ण integration
📊 performance तुलना (benchmark)
benchmark environment
- CPU: 13th Gen Intel(R) Core(TM) i5-13600K (~4.70-4.80 GHz)
- Runtime: Node.js 22.17.0 (x64-win32) with --expose-gc
- Tool: Mitata
97MB बड़े file की parsing:
- stax-xml: 1.05s, memory 8.89MB
- fast-xml-parser: 4.41s, memory 886.33MB
- txml: 1.02s, memory 897.50MB
🌐 व्यापक compatibility
सिर्फ web standard APIs का उपयोग करके सभी JavaScript runtimes में काम करता है:
- Node.js (v18+)
- Bun, Deno
- web browser
- Edge Runtime (Vercel, Cloudflare Workers)
📦 installation और शुरुआत
npm install stax-xml
import { StaxXmlParser, XmlEventType } from 'stax-xml';
// XML string से stream बनाना
const stream = new ReadableStream({
start(controller) {
controller.enqueue(new TextEncoder().encode(xmlContent));
controller.close();
}
});
// asynchronous parsing
const parser = new StaxXmlParser(stream);
for await (const event of parser) {
if (event.type === XmlEventType.START_ELEMENT) {
console.log(`tatva: ${event.name}`, event.attributes);
}
}
📄 project जानकारी
- GitHub: https://github.com/clickin/stax-xml
- दस्तावेज़: https://clickin.github.io/stax-xml
- NPM: https://www.npmjs.com/package/stax-xml
- लाइसेंस: MIT
※ लाइसेंस से संबंधित संदर्भ: यह library JSR 173: Streaming API for XML में प्रस्तावित StAX की अवधारणा से प्रेरित है, लेकिन मैं JSR के लाइसेंस की शर्तों को स्पष्ट रूप से समझ नहीं पाया। अगर किसी को StAX नाम से जुड़े लाइसेंस प्रावधानों की जानकारी हो, तो कृपया सलाह दें।
1 टिप्पणियां
दस्तावेज़ में ईमानदारी और लगन महसूस हुई, इसलिए अच्छा लगा।
अच्छे से पढ़ा!