Dokunduğunuz her SOAP servisi, tükettiğiniz her RSS beslemesi, değiştirdiğiniz her SVG — hepsi XML'dir. JavaScript'in tarayıcıda iki yerleşik ayrıştırma yolu ve Node.js için sağlam bir npm kütüphanesi vardır. Zor kısım ayrıştırmanın kendisi değildir; asıl sorun ortaya çıkan DOM'da gezinmek, ad alanlarını ele almak ve ilk seferinde herkesi yakalayan tuhaflıklara takılmamaktır. Gerçek desenleri birlikte inceleyelim.
DOMParser — Tarayıcıda XML Ayrıştırma
Tarayıcının yerleşik
DOMParser
API'si bir XML dizesini DOM belgesine dönüştürür. Ayrıştırıcının katı XML kurallarını uygulaması için
('text/html' değil) 'application/xml' MIME türünü kullanın:
const xmlString = `<?xml version="1.0" encoding="UTF-8"?>
<library>
<book isbn="978-0-13-110362-7">
<title>The C Programming Language</title>
<authors>
<author>Brian W. Kernighan</author>
<author>Dennis M. Ritchie</author>
</authors>
<year>1988</year>
<price currency="USD">45.99</price>
</book>
<book isbn="978-0-201-63361-0">
<title>The Pragmatic Programmer</title>
<authors>
<author>Andrew Hunt</author>
<author>David Thomas</author>
</authors>
<year>1999</year>
<price currency="USD">52.00</price>
</book>
</library>`;
const parser = new DOMParser();
const doc = parser.parseFromString(xmlString, 'application/xml');
// Her zaman önce ayrıştırma hatalarını kontrol edin
const parseError = doc.querySelector('parsererror');
if (parseError) {
throw new Error('XML parse failed: ' + parseError.textContent);
}
console.log(doc.documentElement.tagName); // libraryJSON.parse()'den farklı olarak,
DOMParser ayrıştırma başarısız olduğunda bir <parsererror> elementi içeren
belge döndürür — istisna fırlatmaz. Hata kontrolünü atlarsanız, hatalı biçimlendirilmiş belge üzerinde
sessizce çalışırsınız ve ileride kafa karıştırıcı sonuçlar elde edersiniz.DOM'da Gezinme — getElementsByTagName ve querySelector
Ayrıştırılmış bir belgeniz olduğunda, element bulmak için iki ana API bulunur. İkisi de çalışır ama farklı güçleri vardır:
// getElementsByTagName — canlı bir HTMLCollection döndürür
const books = doc.getElementsByTagName('book');
console.log(books.length); // 2
// querySelector / querySelectorAll — CSS seçici sözdizimi, NodeList döndürür
const firstTitle = doc.querySelector('title').textContent;
console.log(firstTitle); // The C Programming Language
// Tüm başlıkları al
const titles = [...doc.querySelectorAll('title')].map(el => el.textContent);
console.log(titles);
// ['The C Programming Language', 'The Pragmatic Programmer']
// Nitelikleri okuma
const firstBook = doc.querySelector('book');
const isbn = firstBook.getAttribute('isbn');
console.log(isbn); // 978-0-13-110362-7
// Fiyattan currency niteliğini okuma
const priceEl = firstBook.querySelector('price');
console.log(priceEl.textContent); // 45.99
console.log(priceEl.getAttribute('currency')); // USDHedefli aramalar için querySelector'ı tercih ederim — CSS seçici sözdizimi
tanıdık ve özdür. Belirli bir etiketli tüm elementlere ihtiyacınız olduğunda ve canlı bir koleksiyon istediğinizde
getElementsByTagName'i kullanın (pratikte spread ile NodeList genellikle daha temizdir).
Yapılandırılmış Veri Çıkarma — Pratik Bir Desen
Bir XML belgesini temiz bir JavaScript nesne dizisine nasıl eşleyeceğiniz aşağıda açıklanmıştır — gerçek bir XML API yanıtı tüketirken kullanacağınız desen:
function parseLibraryXml(xmlString) {
const parser = new DOMParser();
const doc = parser.parseFromString(xmlString, 'application/xml');
if (doc.querySelector('parsererror')) {
throw new Error('Invalid XML');
}
return [...doc.querySelectorAll('book')].map(book => ({
isbn: book.getAttribute('isbn'),
title: book.querySelector('title').textContent.trim(),
authors: [...book.querySelectorAll('author')].map(a => a.textContent.trim()),
year: parseInt(book.querySelector('year').textContent, 10),
price: {
amount: parseFloat(book.querySelector('price').textContent),
currency: book.querySelector('price').getAttribute('currency')
}
}));
}
const books = parseLibraryXml(xmlString);
console.log(books[0].title); // The C Programming Language
console.log(books[0].authors); // ['Brian W. Kernighan', 'Dennis M. Ritchie']
console.log(books[0].price.amount); // 45.99Ad Alanlı XML ile Çalışma
Ad alanları, çoğu geliştiricinin takıldığı yerdir. SOAP yanıtları, Atom beslemeleri ve SVG'nin hepsi
XML ad alanları kullanır — ve SOAP belgesinde naif bir querySelector('body'),
element aslında soap:Body olduğu için null döndürür. Bunu doğru şekilde ele alma yöntemi:
const soapResponse = `<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:m="http://www.example.com/orders">
<soap:Header/>
<soap:Body>
<m:GetOrderResponse>
<m:OrderId>ORD-5521</m:OrderId>
<m:Status>Shipped</m:Status>
<m:Total currency="EUR">289.50</m:Total>
</m:GetOrderResponse>
</soap:Body>
</soap:Envelope>`;
const parser = new DOMParser();
const doc = parser.parseFromString(soapResponse, 'application/xml');
// Seçenek 1: getElementsByTagNameNS — açık ad alanı URI'si
const SOAP_NS = 'http://schemas.xmlsoap.org/soap/envelope/';
const ORDER_NS = 'http://www.example.com/orders';
const body = doc.getElementsByTagNameNS(SOAP_NS, 'Body')[0];
const orderId = doc.getElementsByTagNameNS(ORDER_NS, 'OrderId')[0].textContent;
const status = doc.getElementsByTagNameNS(ORDER_NS, 'Status')[0].textContent;
console.log(orderId); // ORD-5521
console.log(status); // Shipped
// Seçenek 2: Ad alanı çözücüyle XPath (daha esnek)
function nsResolver(prefix) {
const namespaces = {
soap: 'http://schemas.xmlsoap.org/soap/envelope/',
m: 'http://www.example.com/orders'
};
return namespaces[prefix] || null;
}
const xpathResult = doc.evaluate(
'//m:OrderId',
doc,
nsResolver,
XPathResult.STRING_TYPE,
null
);
console.log(xpathResult.stringValue); // ORD-5521evaluate() ile XPath Sorguları
XPath, XML belgeleri için bir sorgu dilidir. Tarayıcı bunu document.evaluate() aracılığıyla sunar.
XML için CSS seçicilerinden daha güçlüdür — nitelik değerine, konuma, metin içeriğine ve ataya göre
sorgulama yapabilirsiniz.
Tam ifade sözdizimi için MDN XPath belgelerine
bakın:
// Daha önce kullandığımız kütüphane XML belgesini kullanarak
function xpath(doc, expression, contextNode = doc) {
const result = doc.evaluate(
expression,
contextNode,
null, // ad alanı çözücü — ad alansız XML için null
XPathResult.ANY_TYPE,
null
);
return result;
}
// Tüm kitap başlıklarını al
const titlesResult = xpath(doc, '//book/title');
const titles = [];
let node;
while ((node = titlesResult.iterateNext())) {
titles.push(node.textContent);
}
console.log(titles);
// ['The C Programming Language', 'The Pragmatic Programmer']
// Belirli ISBN'li kitabı al
const bookResult = doc.evaluate(
'//book[@isbn="978-0-13-110362-7"]/title',
doc, null,
XPathResult.STRING_TYPE,
null
);
console.log(bookResult.stringValue); // The C Programming Language
// 50 dolardan pahalı kitapları al
const expensiveResult = xpath(doc, '//book[price > 50]/title');
let expensiveNode;
while ((expensiveNode = expensiveResult.iterateNext())) {
console.log(expensiveNode.textContent); // The Pragmatic Programmer
}Node.js — fast-xml-parser (En İyi Seçenek)
Node.js'de DOMParser yoktur. İki seçeneğiniz var:
yerleşik
node:stream tabanlı SAX yaklaşımını kullanın (zahmetli) ya da
fast-xml-parser
kullanın (çoğu kullanım senaryosu için doğru seçim). Hızlı, bağımlılıksız ve düz JavaScript nesneleri döndürür:
npm install fast-xml-parserimport { XMLParser } from 'fast-xml-parser';
const xmlString = `<?xml version="1.0"?>
<library>
<book isbn="978-0-13-110362-7">
<title>The C Programming Language</title>
<year>1988</year>
<price currency="USD">45.99</price>
</book>
<book isbn="978-0-201-63361-0">
<title>The Pragmatic Programmer</title>
<year>1999</year>
<price currency="USD">52.00</price>
</book>
</library>`;
const parser = new XMLParser({
ignoreAttributes: false, // XML niteliklerini dahil et
attributeNamePrefix: '@_', // nitelikleri elementlerden ayırmak için önek ekle
isArray: (tagName) => tagName === 'book' // <book>'u her zaman dizi olarak işle
});
const result = parser.parse(xmlString);
const books = result.library.book;
books.forEach(book => {
console.log(book.title); // The C Programming Language
console.log(book['@_isbn']); // 978-0-13-110362-7
console.log(book.price['#text']); // 45.99
console.log(book.price['@_currency']); // USD
});fast-xml-parser bir öğe için nesne, birçok öğe için dizi döndürür.
isArray seçeneği adlandırılmış etiketler için tutarlı dizi davranışı zorlar —
tekrarlanabileceğini bildiğiniz elementler için her zaman kullanın.Node.js'de Hata Yönetimi
import { XMLParser, XMLValidator } from 'fast-xml-parser';
function parseXmlSafely(xmlString) {
// Önce doğrula — true veya hata nesnesi döndürür
const validation = XMLValidator.validate(xmlString);
if (validation !== true) {
throw new Error(`Invalid XML: ${validation.err.msg} at line ${validation.err.line}`);
}
const parser = new XMLParser({ ignoreAttributes: false, attributeNamePrefix: '@_' });
return parser.parse(xmlString);
}
try {
const data = parseXmlSafely(xmlString);
console.log(data);
} catch (err) {
console.error('XML parsing failed:', err.message);
}İlgili Araçlar
JavaScript projelerinde XML ile çalışırken: XML Biçimlendirici küçültülmüş yanıtları güzelce biçimlendirmek için, XML Doğrulayıcı ayrıştırmadan önce iyi biçimliliği kontrol etmek için, XML XPath Test Aracı XPath sorgularını denemek için, ve XML'den JSON'a daha basit bir yapıya dönüştürmek istiyorsanız.
Özet
Tarayıcıda, 'application/xml' ile DOMParser temel tercihinizdir —
sadece parsererror'u kontrol etmeyi unutmayın. Ad alanlı XML için
getElementsByTagNameNS veya ad alanı çözücüyle XPath kullanın. Node.js'de
fast-xml-parser DOM yükü olmadan temiz JavaScript nesneleri sunar.
Buradaki desenler gerçek dünya XML ayrıştırma senaryolarının %95'ini kapsar — SOAP yanıtları, RSS beslemeleri,
yapılandırma dosyaları ve daha fazlası.