11 puan yazan click 2025-09-22 | 1 yorum | WhatsApp'ta paylaş

İş 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: fetch API 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


※ 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

 
honglu 2025-09-22

Belgedeki özen ve emek hissi çok hoştu.

Keyifle okudum!