Chapter 35: Accessing Nodes
XML DOM – Accessing Nodes.
I will explain it as if I am your personal teacher sitting next to you — slowly, clearly, with many small-to-medium examples, visual drawings (in text), real-life analogies, common beginner mistakes, and practical JavaScript code you can copy-paste and run right now.
1. The most important mindset before we start
When you work with XML DOM in JavaScript, you are walking through a tree house.
- Every tag is a room (Element node)
- Every piece of text is a note stuck on the wall (Text node)
- Every attribute is a label on the door (Attribute node)
- Comments, processing instructions, CDATA sections… are other kinds of objects in the rooms
Accessing nodes means:
- Finding a specific room (or all rooms that match some description)
- Entering the room and looking at what’s inside (text, children, attributes)
- Sometimes changing what’s inside or adding/removing things
Almost everything you do with XML DOM starts with finding nodes.
2. The 5 most important ways to find / access nodes (in order of how often you will use them)
| # | Method | Returns | Best used when… | Modern / classic? | Example line |
|---|---|---|---|---|---|
| 1 | querySelector() | First matching Element or null | You want one specific element | Modern (2011+) | xmlDoc.querySelector(“title”) |
| 2 | querySelectorAll() | NodeList of matching Elements | You want all elements that match | Modern (2011+) | xmlDoc.querySelectorAll(“price”) |
| 3 | getElementById() | One Element or null | You know the id attribute | Classic | xmlDoc.getElementById(“B101”) |
| 4 | getElementsByTagName() | HTMLCollection of Elements | You want all elements with a certain tag name | Classic | xmlDoc.getElementsByTagName(“author”) |
| 5 | getElementsByClassName() | HTMLCollection | You are using class attributes (rare in pure XML) | Classic | (rarely used in XML) |
Modern recommendation (2025–2026)
Use querySelector and querySelectorAll for almost everything. They are the most flexible, readable, and powerful methods.
3. Real XML we will work with (copy this for testing)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<?xml version="1.0" encoding="UTF-8"?> <library> <book id="B101" lang="en" category="self-help"> <!-- Popular book on habits --> <title>Atomic Habits</title> <author>James Clear</author> <year>2018</year> <price currency="INR">499.00</price> <inStock>true</inStock> </book> <book id="B102" lang="en" category="finance"> <title>Rich Dad Poor Dad</title> <author>Robert Kiyosaki</author> <year>1997</year> <price currency="INR">349.00</price> <inStock>false</inStock> </book> <magazine id="M001"> <title>India Today</title> <issue>July 2025</issue> <price currency="INR">120.00</price> </magazine> </library> |
Save it as library.xml or paste it into a string.
4. Example 1 – Using querySelector (the modern favorite)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
// Option A: from string const xmlString = `... paste the library XML here ...`; const parser = new DOMParser(); const xmlDoc = parser.parseFromString(xmlString, "application/xml"); // Option B: from AJAX response (most common real use) xhr.onload = function() { if (xhr.status === 200) { const xmlDoc = xhr.responseXML; // ... continue below ... } }; // Examples: // 1. Get first <title> anywhere const firstTitle = xmlDoc.querySelector("title"); console.log(firstTitle.textContent); // "Atomic Habits" // 2. Get the <title> of the first <book> const firstBookTitle = xmlDoc.querySelector("book title"); console.log(firstBookTitle.textContent); // "Atomic Habits" // 3. Get book with id="B102" const secondBook = xmlDoc.querySelector('book[id="B102"]'); console.log(secondBook.querySelector("title").textContent); // "Rich Dad Poor Dad" // 4. Get all books that are out of stock const outOfStock = xmlDoc.querySelector('book inStock[text()="false"]'); console.log(outOfStock.querySelector("title").textContent); // "Rich Dad Poor Dad" // 5. Get price with currency="INR" const inrPrices = xmlDoc.querySelectorAll('price[currency="INR"]'); inrPrices.forEach(p => { console.log(p.textContent); // 499.00 349.00 120.00 }); |
5. Example 2 – Using querySelectorAll + looping
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// Get all book titles const allTitles = xmlDoc.querySelectorAll("book title"); console.log("Found " + allTitles.length + " books:"); allTitles.forEach((title, index) => { console.log(`${index + 1}. ${title.textContent}`); }); // Output: // Found 2 books: // 1. Atomic Habits // 2. Rich Dad Poor Dad |
6. Example 3 – Accessing attributes & checking existence
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// Get first book const firstBook = xmlDoc.querySelector("book"); // Check if attribute exists if (firstBook.hasAttribute("id")) { console.log("ID:", firstBook.getAttribute("id")); // B101 } // Get all books with lang="en" const englishBooks = xmlDoc.querySelectorAll('book[lang="en"]'); console.log("English books:", englishBooks.length); // 2 // Get category of second book const secondBook = xmlDoc.querySelectorAll("book")[1]; console.log("Category:", secondBook.getAttribute("category")); // finance |
7. Example 4 – Walking the tree manually (parent, children, siblings)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
const firstBook = xmlDoc.querySelector("book"); // Parent of <title> const title = firstBook.querySelector("title"); console.log(title.parentNode.tagName); // "book" // All direct children of first <book> const children = firstBook.childNodes; console.log("Children count:", children.length); // usually 9–11 (text nodes + elements) // Only element children (skip text & comments) const elementChildren = firstBook.children; console.log("Element children:", elementChildren.length); // 4 or 5 // First child element console.log("First child:", firstBook.firstElementChild.tagName); // "title" // Next sibling const author = title.nextElementSibling; console.log("Next after title:", author.tagName); // "author" |
8. Common beginner mistakes & how to avoid them
Mistake 1 — Forgetting about text nodes between elements
|
0 1 2 3 4 5 6 7 8 |
for (let child of firstBook.childNodes) { console.log(child.tagName); // many undefined — because text nodes } |
Fix: Use .children or check nodeType === 1
Mistake 2 — Using innerHTML on XML DOM
|
0 1 2 3 4 5 6 |
title.innerHTML = "<b>New Title</b>"; // Often ignored or breaks in pure XML DOM |
Fix: Use textContent or create real elements
Mistake 3 — Assuming querySelector returns text
|
0 1 2 3 4 5 6 7 8 |
const price = xmlDoc.querySelector("price"); // Element node console.log(price); // <price>...</price> console.log(price.value); // undefined! |
Fix: price.textContent or price.firstChild.nodeValue
Summary – Quick reference table
| You want to… | Best method / pattern |
|---|---|
| Find first element by tag | querySelector(“title”) |
| Find all books | querySelectorAll(“book”) |
| Find by attribute | querySelector(‘book[id=”B101″]’) |
| Find by text content | querySelector(‘inStock[text()=”false”]’) |
| Get all direct element children | element.children |
| Loop only elements (skip text/comments) | for (let child of parent.children) |
| Get text safely | element.textContent.trim() |
| Check if attribute exists | element.hasAttribute(“currency”) |
Would you like to continue with any of these deeper topics?
- Ignoring whitespace text nodes (very common need)
- Accessing & creating CDATA sections
- Working with namespaces (SOAP, RSS, UBL, GST e-invoice…)
- Walking the tree manually in detail (firstChild, nextSibling, parentNode…)
- Real-world patterns (parsing RSS, SOAP response, config file)
- Debugging when you get null or wrong nodes
Just tell me which direction you want to go next! 😊
