Skip to content

XML DOM Advanced

The XML Document Object Model (DOM) provides a standard way to access and manipulate the structure and content of XML documents. While basic traversal was introduced earlier, this section covers more advanced techniques for reading and modifying XML data using DOM APIs, typically within a JavaScript environment.

Note: The examples use standard DOM methods common in web browsers. Modern JavaScript offers convenient alternatives like querySelector and querySelectorAll which accept CSS selectors (and sometimes basic XPath) for node selection, often leading to more concise code.

Assume xmlDoc is a variable holding a parsed XML DOM object (e.g., loaded via fetch and DOMParser).

To retrieve the text content inside an element:

Using specific DOM traversal (less common now):

// Get the first <title> element
const firstTitleElement = xmlDoc.getElementsByTagName("title")[0];
// Access its first child node (which should be the text node)
const textNode = firstTitleElement.childNodes[0];
// Get the value of the text node
const titleText = textNode.nodeValue;

Using the simpler .textContent property (Recommended):

// Get the text content of the first <title> element directly
const titleText = xmlDoc.getElementsByTagName("title")[0].textContent;

Explanation: .textContent conveniently concatenates the text content of all child nodes, which is usually what’s desired. The childNodes[0].nodeValue approach is more explicit but brittle if the element contains comments or other node types before the text.

To retrieve the value of an attribute associated with an element:

// Get the first <title> element
const firstTitleElement = xmlDoc.getElementsByTagName("title")[0];
// Get the value of its 'lang' attribute
const langValue = firstTitleElement.getAttribute("lang"); // Returns "en" in the example

If the attribute doesn’t exist, getAttribute() returns null.

To modify the text content of an element:

Using specific DOM manipulation (less common):

// Get the first <title> element's text node
const textNode = xmlDoc.getElementsByTagName("title")[0].childNodes[0];
// Change its value
textNode.nodeValue = "Easy XML Cooking";

Using the simpler .textContent property (Recommended):

// Get the first <title> element
const firstTitleElement = xmlDoc.getElementsByTagName("title")[0];
// Change its text content
firstTitleElement.textContent = "Easy XML Cooking";

Setting .textContent replaces all existing child nodes of the element with a single new text node.

The setAttribute() method adds a new attribute or changes the value of an existing one.

// Get all <book> elements
const books = xmlDoc.getElementsByTagName("book");
// Add/update an 'edition' attribute for each book
for (let i = 0; i < books.length; i++) {
books[i].setAttribute("edition", "first");
}

If the ‘edition’ attribute already exists, its value will be updated to ‘first’. If it doesn’t exist, it will be created.

To add a new element (e.g., <edition>First</edition>) to an existing element:

  1. Use createElement() to create the new element node (<edition>).
  2. Use createTextNode() to create the text content (First). (Alternatively, set .textContent after creating the element).
  3. Use appendChild() to add the text node as a child of the new element node.
  4. Use appendChild() again to add the new element (with its text child) to the desired parent element (e.g., the first <book>).

Example:

// 1. Create the new <edition> element
const newElement = xmlDoc.createElement("edition");
// 2. Create the text content
const newText = xmlDoc.createTextNode("First");
// 3. Append text to the new element
newElement.appendChild(newText);
// --- OR using textContent (simpler) ---
// const newElement = xmlDoc.createElement("edition");
// newElement.textContent = "First";
// -------------------------------------
// 4. Get the target parent element (first <book>)
const firstBook = xmlDoc.getElementsByTagName("book")[0];
// 5. Append the new <edition> element to the first <book>
firstBook.appendChild(newElement);

To remove a node (element, text node, comment, etc.), you need a reference to the node itself and its parent node. Then use the parent’s removeChild() method.

Example: Remove the first child node (could be text, an element, etc.) from the first <book> element:

// Get the first <book> element
const firstBook = xmlDoc.getElementsByTagName("book")[0];
// Check if it has any child nodes
if (firstBook.hasChildNodes()) {
// Get the first child node
const nodeToRemove = firstBook.childNodes[0];
// Remove it using the parent
firstBook.removeChild(nodeToRemove);
}

Important Note on childNodes: The childNodes collection includes all node types, including elements, text nodes (even those containing only whitespace), and comments. This can sometimes lead to unexpected results if you assume childNodes[0] is always the first element child. Be mindful of whitespace nodes between elements which parsers might create. If you only want element children, consider using the .children property or iterating childNodes and checking nodeType.

Exploring the full XML DOM specification (e.g., on MDN Web Docs) reveals many more methods for detailed navigation and manipulation.