Jeder SOAP-Service, den Sie je angebunden haben, jeder RSS-Feed, den Sie konsumiert haben, jedes SVG, das Sie manipuliert haben — sie alle sind XML. JavaScript hat zwei eingebaute Wege, es im Browser zu parsen, und eine solide npm-Bibliothek für Node.js. Der knifflige Teil ist nicht das Parsen selbst; es ist das Navigieren im resultierenden DOM, der Umgang mit Namespaces und das Vermeiden der Eigenheiten, die jeden beim ersten Mal erwischen. Gehen wir die echten Muster durch.
DOMParser — XML im Browser parsen
Die eingebaute
DOMParser-API
des Browsers konvertiert einen XML-String in ein DOM-Dokument. Verwenden Sie den MIME-Typ 'application/xml'
(nicht 'text/html'), damit der Parser strenge XML-Regeln anwendet:
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');
// Zuerst immer auf Parse-Fehler prüfen
const parseError = doc.querySelector('parsererror');
if (parseError) {
throw new Error('XML parse failed: ' + parseError.textContent);
}
console.log(doc.documentElement.tagName); // libraryJSON.parse(), das eine Exception wirft,
gibt DOMParser bei einem Parsing-Fehler ein Dokument zurück, das ein <parsererror>-Element
enthält — es wirft keine Exception. Wenn Sie die Fehlerprüfung überspringen, arbeiten Sie stillschweigend an einem
fehlerhaften Dokument und erhalten verwirrende Ergebnisse.Im DOM navigieren — getElementsByTagName vs querySelector
Sobald Sie ein gepartes Dokument haben, stehen Ihnen zwei Haupt-APIs zur Elementsuche zur Verfügung. Beide funktionieren, haben aber unterschiedliche Stärken:
// getElementsByTagName — gibt eine Live-HTMLCollection zurück
const books = doc.getElementsByTagName('book');
console.log(books.length); // 2
// querySelector / querySelectorAll — CSS-Selektor-Syntax, gibt NodeList zurück
const firstTitle = doc.querySelector('title').textContent;
console.log(firstTitle); // The C Programming Language
// Alle Titel abrufen
const titles = [...doc.querySelectorAll('title')].map(el => el.textContent);
console.log(titles);
// ['The C Programming Language', 'The Pragmatic Programmer']
// Attribute lesen
const firstBook = doc.querySelector('book');
const isbn = firstBook.getAttribute('isbn');
console.log(isbn); // 978-0-13-110362-7
// Das currency-Attribut aus price lesen
const priceEl = firstBook.querySelector('price');
console.log(priceEl.textContent); // 45.99
console.log(priceEl.getAttribute('currency')); // USDIch bevorzuge querySelector für gezielte Suchen — die CSS-Selektor-Syntax ist
vertraut und prägnant. Verwenden Sie getElementsByTagName, wenn Sie alle Elemente mit einem
bestimmten Tag und eine Live-Collection benötigen (obwohl in der Praxis eine Spread-NodeList meist übersichtlicher ist).
Strukturierte Daten extrahieren — Ein praktisches Muster
So mappen Sie ein XML-Dokument in ein sauberes JavaScript-Array von Objekten — das Muster, das Sie beim Verarbeiten einer echten XML-API-Antwort verwenden werden:
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.99Namespace-behaftetes XML verarbeiten
Namespaces sind der Punkt, an dem die meisten Entwickler an eine Wand stoßen. SOAP-Antworten, Atom-Feeds und SVG
verwenden alle XML-Namespaces — und ein naives querySelector('body') gibt null in einem SOAP-Dokument
zurück, weil das Element eigentlich soap:Body heißt. So gehen Sie damit korrekt um:
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');
// Option 1: getElementsByTagNameNS — explizite Namespace-URI
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
// Option 2: XPath mit Namespace-Resolver (flexibler)
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-5521XPath-Abfragen mit evaluate()
XPath ist eine Abfragesprache für XML-Dokumente. Der Browser stellt sie über
document.evaluate() bereit. Sie ist leistungsfähiger als CSS-Selektoren für XML — Sie können
nach Attributwert, Position, Textinhalt und Vorfahren abfragen.
Die vollständige Ausdruckssyntax finden Sie in der MDN-XPath-Dokumentation:
// Unser library-XML-Dokument von zuvor verwenden
function xpath(doc, expression, contextNode = doc) {
const result = doc.evaluate(
expression,
contextNode,
null, // Namespace-Resolver — null für XML ohne Namespaces
XPathResult.ANY_TYPE,
null
);
return result;
}
// Alle Buchtitel abrufen
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']
// Das Buch mit einer bestimmten ISBN abrufen
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
// Bücher über $50 abrufen
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 (Die beste Option)
Node.js hat keinen DOMParser. Sie haben zwei Möglichkeiten: den
eingebauten
SAX-Ansatz über node:stream (umständlich) oder
fast-xml-parser
(die richtige Wahl für die meisten Anwendungsfälle). Es ist schnell, ohne externe Abhängigkeiten und gibt einfache JavaScript-Objekte zurück:
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-Attribute einbeziehen
attributeNamePrefix: '@_', // Attribute mit Präfix versehen, um sie von Elementen zu unterscheiden
isArray: (tagName) => tagName === 'book' // <book> immer als Array behandeln
});
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 für ein Element ein Objekt
und für viele ein Array zurück. Die isArray-Option erzwingt konsistentes Array-Verhalten für
benannte Tags — verwenden Sie sie immer für Elemente, die sich wiederholen können.Fehlerbehandlung in Node.js
import { XMLParser, XMLValidator } from 'fast-xml-parser';
function parseXmlSafely(xmlString) {
// Zuerst validieren — gibt true oder ein Fehlerobjekt zurück
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);
}Verwandte Tools
Beim Arbeiten mit XML in JavaScript-Projekten: XML-Formatierer zum Formatieren komprimierter Antworten, XML-Validator zur Prüfung der Wohlgeformtheit vor dem Parsen, XML-XPath-Tester zum Experimentieren mit XPath-Abfragen, und XML zu JSON zur Konvertierung in eine einfachere Struktur.
Fazit
Im Browser ist DOMParser mit 'application/xml' Ihre erste Wahl —
denken Sie nur daran, auf parsererror zu prüfen. Für namespace-behaftetes XML verwenden Sie
getElementsByTagNameNS oder XPath mit einem Namespace-Resolver. In Node.js liefert
fast-xml-parser saubere JavaScript-Objekte ohne den DOM-Overhead.
Die Muster hier decken 95% der realen XML-Parsing-Szenarien ab — SOAP-Antworten, RSS-Feeds,
Konfigurationsdateien und mehr.