StAX-XML: JavaScript/TypeScript için yüksek performanslı akış tabanlı XML ayrıştırıcısı
(github.com/Clickin)İş yerimde Java ile yazılmış legacy servisler var ve iletişim XML tabanlı. Legacy servisi backend olarak bırakıp js tabanlı yeni bir web servisi geliştirmeye çalışırken tam içime sinen bir XML parser bulamayınca kendim yazdım.
StAX tabanlı pull yaklaşımıyla XML ayrıştırıyor ve asenkron bir uygulama sunduğu için Stream tabanlı olarak büyük XML dosyalarını da yaklaşık 10MB bellekle ayrıştırabiliyor.
ECMAScript standardında string için azami uzunluk 2^53 - 1 olduğundan, 1GB’ı aşan XML’lerde mecburen SAX parser kullanmak gerekiyordu; bu kütüphanenin buna iyi bir alternatif olacağını düşünüyorum.
İş yerinde ağırlıklı olarak Java kullanıyorum ve Node ekosistemi için ilk kez bir kütüphane geliştiriyorum; eksik gördüğünüz noktaları önerirseniz mümkün olduğunca yansıtmaya çalışırım.
Geçmiş
Başta Java’nın woodstox kütüphanesini wasm’e bağlayıp kullanmayı düşündüm,
ama o sırada wasm’de henüz GC implementasyonu olmadığı için Java’yı wasm’e derlemenin erken olduğunu düşünüp vazgeçtim.
İkinci olarak Rust’ın quick-xml kütüphanesini wasm’e bağlayarak denedim, ancak stream’i wasm’e geçirip işlemenin maliyeti çok yüksek olduğundan mevcut JavaScript XML parser’larına göre performans farkı fazla açıldı ve bu yaklaşımı bıraktım.
Sonunda saf TypeScript ile yazmaya karar verdim ve çeşitli yapay zeka araçlarının da yardımıyla V8 motorunu hedefleyen birçok optimizasyon uyguladım.
🚀 Başlıca özellikler
Tam asenkron akış tabanlı ayrıştırma
- Büyük XML dosyaları (yüzlerce MB~GB) için bellek verimli işleme
- ReadableStream tabanlı, ana thread’i bloke etmeden gerçek zamanlı ayrıştırma
- pull yaklaşımıyla yalnızca ihtiyaç duyulan kadar veri işleme
// 970MB dosya bile 10MB’tan az bellekle işlenebilir
const parser = new StaxXmlParser(largeXmlStream);
for await (const event of parser) {
// Olayları akış halinde işle
}
StAX tarzı olay tabanlı ayrıştırma
Java geliştiricilerine tanıdık gelen pull parser pattern sunarak XML yapısını ayrıntılı biçimde kontrol etmeyi sağlar.
import { StaxXmlParser, isStartElement, isCharacters } from 'stax-xml';
for await (const event of parser) {
if (isStartElement(event)) {
console.log(`요소: ${event.name}`, event.attributes);
} else if (isCharacters(event)) {
console.log(`텍스트: ${event.value}`);
}
}
🛠️ 4 temel bileşen
1. StaxXmlParser (asenkron parser)
- Büyük dosyalar için özel: stream tabanlı, bellek verimli ayrıştırma
- Gerçek zamanlı işleme:
fetchAPI ile entegre şekilde uzak XML’i gerçek zamanlı ayrıştırma - TypeScript type guard: çalışma zamanında tip güvenliği sağlar
2. StaxXmlParserSync (senkron parser)
- Küçük dosyalar için optimize: bellekteki XML string’lerini yüksek hızda ayrıştırma
- Web API yanıtları: senkron iş akışlarında anında işleme
3. StaxXmlWriter (asenkron writer)
- Akış halinde üretim: XML’i doğrudan
WritableStream’e yazma - Gerçek zamanlı yanıt: API sunucusunda büyük XML yanıtları üretme
- Bellek verimli: tüm XML’i bellekte tutmaz
4. StaxXmlWriterSync (senkron writer)
- Anında üretim: bellekte XML string’i oluşturma
- Web sunucusu entegrasyonu: Express, Hono vb. ile kusursuz entegrasyon
📊 Performans karşılaştırması (benchmark)
Benchmark ortamı
- 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 büyük dosya ayrıştırma:
- stax-xml: 1.05s, bellek 8.89MB
- fast-xml-parser: 4.41s, bellek 886.33MB
- txml: 1.02s, bellek 897.50MB
🌐 Genel uyumluluk
Yalnızca web standardı API’leri kullanır, bu sayede tüm JavaScript runtime’larında çalışır:
- Node.js (v18+)
- Bun, Deno
- Web tarayıcıları
- Edge Runtime (Vercel, Cloudflare Workers)
📦 Kurulum ve başlangıç
npm install stax-xml
import { StaxXmlParser, XmlEventType } from 'stax-xml';
// XML string’inden stream oluştur
const stream = new ReadableStream({
start(controller) {
controller.enqueue(new TextEncoder().encode(xmlContent));
controller.close();
}
});
// Asenkron ayrıştırma
const parser = new StaxXmlParser(stream);
for await (const event of parser) {
if (event.type === XmlEventType.START_ELEMENT) {
console.log(`요소: ${event.name}`, event.attributes);
}
}
📄 Proje bilgileri
- GitHub: https://github.com/clickin/stax-xml
- Dokümantasyon: https://clickin.github.io/stax-xml
- NPM: https://www.npmjs.com/package/stax-xml
- Lisans: MIT
※ Lisansla ilgili not: Bu kütüphane, JSR 173: Streaming API for XML içinde önerilen StAX kavramından ilham almıştır; ancak JSR’nin lisans koşullarını net biçimde tespit edemedim. StAX adlandırmasının lisans maddelerini bilen varsa tavsiye paylaşırsa memnun olurum.
1 yorum
Belgedeki özen ve emek hissi çok hoştu.
Keyifle okudum!