Chapter 47: DOM Clone Nodes
XML DOM – Cloning Nodes.
I will explain everything as if I’m your personal teacher sitting next to you — going very slowly, using simple analogies, drawing small trees on the whiteboard, showing before → after examples, warning about every possible trap, and giving you realistic, copy-paste-ready code you can run right now.
1. What does “cloning a node” actually mean?
Cloning = making a copy of an existing node (or subtree) so you have a separate, independent version of it.
The cloned node is not the original — it is a new node in memory.
Key questions people usually have:
- Is the clone attached to the document? → No, you decide where to put it (or you can leave it floating)
- Does the clone share the same memory as the original? → No, it is a separate object
- Can changes to the clone affect the original? → Normally no — unless you clone shallowly and share some references
2. The two kinds of cloning — and why it matters
| Method | Syntax example | Depth copied | Copies attributes? | Copies event listeners? | Copies child nodes? | Most common use case |
|---|---|---|---|---|---|---|
| cloneNode(false) | node.cloneNode(false) | Shallow — only the node itself | Yes | No | No | Duplicate a single element without its children |
| cloneNode(true) | node.cloneNode(true) | Deep — node + all descendants | Yes | No | Yes | Copy entire subtrees (most common in real work) |
Very important rule (you must remember this forever):
cloneNode() never copies event listeners (onclick, addEventListener, etc.) It only copies the structure, attributes, and text — not behavior.
3. Visual before / after – Cloning different ways
Original XML (simplified):
|
0 1 2 3 4 5 6 7 8 9 10 11 12 |
<library> <book id="101"> <title>Atomic Habits</title> <author>James Clear</author> <price currency="INR">499.00</price> </book> </library> |
Case 1 – Shallow clone (cloneNode(false))
|
0 1 2 3 4 5 6 7 |
const originalBook = xmlDoc.querySelector("book"); const shallowClone = originalBook.cloneNode(false); |
Result — the clone has only the <book> tag + attributes:
|
0 1 2 3 4 5 6 |
<book id="101" lang="en" category="self-help"></book> |
→ no children, no text inside
Case 2 – Deep clone (cloneNode(true))
|
0 1 2 3 4 5 6 |
const deepClone = originalBook.cloneNode(true); |
Result — full copy of the entire subtree:
|
0 1 2 3 4 5 6 7 8 9 10 |
<book id="101" lang="en" category="self-help"> <title>Atomic Habits</title> <author>James Clear</author> <price currency="INR">499.00</price> </book> |
→ everything is copied, but it is not yet attached to the document
4. Complete working example – Different cloning scenarios
|
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>XML DOM – Cloning Nodes (Live Demo)</title> <style> body { font-family: Arial, sans-serif; margin: 40px; line-height: 1.6; background: #f9fafb; } button { padding: 12px 24px; margin: 8px 12px 8px 0; background: #6366f1; color: white; border: none; border-radius: 6px; cursor: pointer; } button:hover { background: #4f46e5; } pre { background: #f3e8ff; padding: 20px; border-radius: 8px; white-space: pre-wrap; font-size: 15px; max-height: 400px; overflow-y: auto; } .note { color: #6b7280; font-style: italic; margin: 12px 0; } </style> </head> <body> <h2>XML DOM – Cloning Nodes (Live Demo)</h2> <p>Click buttons one by one — watch how clones are created and attached.</p> <button onclick="resetXML()">1. Reset to original XML</button><br><br> <button onclick="cloneShallow()">2. Shallow clone of first <book></button> <button onclick="cloneDeep()">3. Deep clone of first <book></button> <button onclick="cloneAndAttach()">4. Deep clone + attach as last book</button> <button onclick="cloneAndInsertBefore()">5. Deep clone + insert before second book</button> <button onclick="clonePrice()">6. Clone <price> element to second book</button> <h3>Current XML structure:</h3> <pre id="output">Original XML will appear after reset…</pre> <script> let xmlDoc = null; const output = document.getElementById("output"); const originalXML = `<?xml version="1.0" encoding="UTF-8"?> <library> <book id="101"> <title>Atomic Habits</title> <author>James Clear</author> <price currency="INR">499.00</price> </book> <book id="102"> <title>Rich Dad Poor Dad</title> </book> </library>`; function resetXML() { const parser = new DOMParser(); xmlDoc = parser.parseFromString(originalXML, "application/xml"); if (xmlDoc.querySelector("parsererror")) { output.innerHTML = "XML parsing error!"; return; } showCurrentXML(); } function showCurrentXML() { const serializer = new XMLSerializer(); let xml = serializer.serializeToString(xmlDoc); xml = xml.replace(/> *</g, '>\n<'); // pretty print output.textContent = xml; } // ──────────────────────────────────────────────── // 2. Shallow clone — only the <book> tag + attributes // ──────────────────────────────────────────────── function cloneShallow() { if (!xmlDoc) return resetXML(); const originalBook = xmlDoc.querySelector("book"); const shallowClone = originalBook.cloneNode(false); // Show what we got const serializer = new XMLSerializer(); output.textContent = "Shallow clone result:\n" + serializer.serializeToString(shallowClone); console.log("Shallow clone created (not attached)"); } // ──────────────────────────────────────────────── // 3. Deep clone — full copy including children // ──────────────────────────────────────────────── function cloneDeep() { if (!xmlDoc) return resetXML(); const originalBook = xmlDoc.querySelector("book"); const deepClone = originalBook.cloneNode(true); const serializer = new XMLSerializer(); output.textContent = "Deep clone result (not attached):\n" + serializer.serializeToString(deepClone); console.log("Deep clone created (not attached)"); } // ──────────────────────────────────────────────── // 4. Deep clone + attach as last child of <library> // ──────────────────────────────────────────────── function cloneAndAttach() { if (!xmlDoc) return resetXML(); const originalBook = xmlDoc.querySelector("book"); const clone = originalBook.cloneNode(true); // Change something so we see it's different clone.setAttribute("id", "CLONED-" + Date.now()); xmlDoc.documentElement.appendChild(clone); showCurrentXML(); console.log("Deep clone attached as last book"); } // ──────────────────────────────────────────────── // 5. Deep clone + insert before second book // ──────────────────────────────────────────────── function cloneAndInsertBefore() { if (!xmlDoc) return resetXML(); const originalBook = xmlDoc.querySelector("book"); const clone = originalBook.cloneNode(true); clone.setAttribute("id", "INSERTED-" + Date.now()); const secondBook = xmlDoc.querySelectorAll("book")[1]; xmlDoc.documentElement.insertBefore(clone, secondBook); showCurrentXML(); console.log("Deep clone inserted before second book"); } // ──────────────────────────────────────────────── // 6. Clone only <price> and attach to second book // ──────────────────────────────────────────────── function clonePrice() { if (!xmlDoc) return resetXML(); const originalPrice = xmlDoc.querySelector("price"); const priceClone = originalPrice.cloneNode(true); const secondBook = xmlDoc.querySelectorAll("book")[1]; secondBook.appendChild(priceClone); showCurrentXML(); console.log("Cloned <price> attached to second book"); } // Start with original resetXML(); </script> </body> </html> |
Summary – Quick reference for cloning nodes
| Goal | Method / Pattern | Important notes / traps |
|---|---|---|
| Copy only the node + attributes | node.cloneNode(false) | No children copied — shallow clone |
| Copy node + all descendants | node.cloneNode(true) | Deep clone — most common in practice |
| Clone and attach immediately | parent.appendChild(original.cloneNode(true)) | Original stays in place, clone is new node |
| Clone and insert at specific position | parent.insertBefore(clone, referenceNode) | Very useful for maintaining order |
| Clone single leaf element | leaf.cloneNode(true) | Usually shallow is enough for leaf nodes |
| Clone attribute | element.getAttributeNode(“name”).cloneNode(false) | Very rare — usually use setAttribute instead |
Would you like to continue with one of these next?
- Cloning nodes with namespaces (very common in real XML)
- Cloning → modifying → attaching (change ID, price, etc. after clone)
- Cloning entire subtrees and inserting at different places
- Deep clone vs shallow clone – detailed comparison with examples
- Real-world patterns — duplicating products, duplicating orders, copying sections
- Debugging when cloned nodes “don’t appear” or have wrong values
Just tell me which direction you want to go next! 😊
