Chaque service SOAP que vous avez touché, chaque flux RSS que vous avez consommé, chaque SVG que vous avez manipulé — ils sont tous en XML. JavaScript dispose de deux façons intégrées de l'analyser dans le navigateur, et d'une solide bibliothèque npm pour Node.js. La partie délicate n'est pas l'analyse elle-même ; c'est la navigation dans le DOM résultant, la gestion des espaces de noms, et le fait d'éviter les pièges qui prennent tout le monde par surprise la première fois. Voici les patterns réels.
DOMParser — Analyser du XML dans le navigateur
L'API
DOMParser
intégrée du navigateur convertit une chaîne XML en document DOM. Utilisez le type MIME 'application/xml'
(et non 'text/html') pour que le parseur applique les règles XML strictes :
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');
// Toujours vérifier les erreurs d'analyse en premier
const parseError = doc.querySelector('parsererror');
if (parseError) {
throw new Error('Échec de l'analyse XML : ' + parseError.textContent);
}
console.log(doc.documentElement.tagName); // libraryJSON.parse() qui lance une exception,
DOMParser retourne un document contenant un élément <parsererror> en cas d'échec
d'analyse — il ne lance pas d'exception. Si vous ignorez la vérification d'erreur, vous opérerez silencieusement
sur un document malformé et obtiendrez des résultats confus en aval.Naviguer dans le DOM — getElementsByTagName vs querySelector
Une fois le document analysé, vous disposez de deux principales API pour trouver des éléments. Les deux fonctionnent, mais elles ont des points forts différents :
// getElementsByTagName — retourne une HTMLCollection vivante
const books = doc.getElementsByTagName('book');
console.log(books.length); // 2
// querySelector / querySelectorAll — syntaxe de sélecteur CSS, retourne NodeList
const firstTitle = doc.querySelector('title').textContent;
console.log(firstTitle); // The C Programming Language
// Obtenir tous les titres
const titles = [...doc.querySelectorAll('title')].map(el => el.textContent);
console.log(titles);
// ['The C Programming Language', 'The Pragmatic Programmer']
// Lire les attributs
const firstBook = doc.querySelector('book');
const isbn = firstBook.getAttribute('isbn');
console.log(isbn); // 978-0-13-110362-7
// Lire l'attribut currency depuis price
const priceEl = firstBook.querySelector('price');
console.log(priceEl.textContent); // 45.99
console.log(priceEl.getAttribute('currency')); // USDJe préfère querySelector pour les recherches ciblées — la syntaxe des sélecteurs CSS est
familière et concise. Utilisez getElementsByTagName lorsque vous avez besoin de tous les éléments avec
une balise donnée et que vous voulez une collection vivante (bien qu'en pratique, un NodeList étalé soit généralement plus propre).
Extraire des données structurées — Un pattern pratique
Voici comment mapper un document XML en un tableau JavaScript propre d'objets — le pattern que vous utiliserez lors de la consommation d'une vraie réponse d'API XML :
function parseLibraryXml(xmlString) {
const parser = new DOMParser();
const doc = parser.parseFromString(xmlString, 'application/xml');
if (doc.querySelector('parsererror')) {
throw new Error('XML invalide');
}
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.99Gérer le XML avec espaces de noms
Les espaces de noms sont là où la plupart des développeurs se heurtent à un mur. Les réponses SOAP, les flux Atom et SVG utilisent tous des
espaces de noms XML — et un naïf querySelector('body') retournera null sur un document SOAP
car l'élément est en réalité soap:Body. Voici comment le gérer correctement :
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 — URI d'espace de noms explicite
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 avec résolveur d'espace de noms (plus flexible)
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-5521Requêtes XPath avec evaluate()
XPath est un langage de requête pour les documents XML. Le navigateur l'expose via
document.evaluate(). Il est plus puissant que les sélecteurs CSS pour XML — vous pouvez
interroger par valeur d'attribut, position, contenu textuel et ascendance.
Consultez la documentation XPath MDN
pour la syntaxe complète des expressions :
// Utilisation de notre document XML bibliothèque précédent
function xpath(doc, expression, contextNode = doc) {
const result = doc.evaluate(
expression,
contextNode,
null, // résolveur d'espace de noms — null pour XML sans espace de noms
XPathResult.ANY_TYPE,
null
);
return result;
}
// Obtenir tous les titres de livres
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']
// Obtenir le livre avec un ISBN spécifique
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
// Obtenir les livres dont le prix est supérieur à 50 $
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 (la meilleure option)
Node.js ne dispose pas de DOMParser. Vous avez deux options : utiliser l'approche SAX basée sur
node:stream
intégrée (pénible), ou utiliser
fast-xml-parser
(le bon choix pour la plupart des cas d'utilisation). Il est rapide, sans dépendance, et retourne de simples objets JavaScript :
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, // inclure les attributs XML
attributeNamePrefix: '@_', // préfixer les attributs pour les distinguer des éléments
isArray: (tagName) => tagName === 'book' // toujours traiter <book> comme un tableau
});
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 vous donnera un
objet pour un élément et un tableau pour plusieurs. L'option isArray force un comportement
de tableau cohérent pour les balises nommées — utilisez-la toujours pour les éléments que vous savez pouvoir se répéter.Gestion des erreurs dans Node.js
import { XMLParser, XMLValidator } from 'fast-xml-parser';
function parseXmlSafely(xmlString) {
// Valider d'abord — retourne true ou un objet d'erreur
const validation = XMLValidator.validate(xmlString);
if (validation !== true) {
throw new Error(`XML invalide : ${validation.err.msg} à la ligne ${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('Échec de l'analyse XML :', err.message);
}Outils connexes
Lorsque vous travaillez avec XML dans des projets JavaScript : Formateur XML pour afficher joliment les réponses minifiées, Validateur XML pour vérifier la bonne forme avant d'analyser, Testeur XPath XML pour expérimenter avec des requêtes XPath, et XML vers JSON si vous souhaitez convertir vers une structure plus simple.
Conclusion
Dans le navigateur, DOMParser avec 'application/xml' est votre solution de référence —
pensez juste à vérifier parsererror. Pour le XML avec espaces de noms, utilisez
getElementsByTagNameNS ou XPath avec un résolveur d'espace de noms. Dans Node.js,
fast-xml-parser vous fournit des objets JavaScript propres sans la surcharge du DOM.
Les patterns présentés ici couvrent 95 % des scénarios d'analyse XML du monde réel — réponses SOAP, flux RSS,
fichiers de configuration et bien plus encore.