File handling XML DOM

XML with DOM

The klyn.io.xml.dom package parses XML into a document tree. DOM is convenient when code needs random access, element lookup, tree edits, or serialization after updates.

Imports

import klyn.io
import klyn.io.xml.dom
import org.w3c.dom

Parse XML Text

DOMParser reads XML from a string, file path, FilePath, or InputSource. The result is a DOMDocument whose documentElement is the root element.

import klyn.io.xml.dom
import org.w3c.dom

xml = """
<catalog>
  <book id="klyn">
    <title>Klyn Guide</title>
  </book>
</catalog>
"""

parser = DOMParser()
document as DOMDocument = parser.parseFromString(xml)
root as DOMElement = document.documentElement

books = root.getElementsByTagName("book")
first = books[0] as DOMElement
print(first.getAttribute("id"))
print(first.textContent.toTrim())

Parse Files

Use parseFromFile when the XML source lives on disk. Invalid XML raises DOMException; filesystem errors raise IOException.

import klyn.io
import klyn.io.xml.dom

parser = DOMParser()
document = parser.parseFromFile(FilePath("catalog.xml"))
print(document.documentElement.tagName)

Build and Serialize

DOM can also create a document programmatically. Append elements and text nodes, then use XMLSerializer to produce XML text.

import klyn.io.xml.dom

document = DOMDocument()
root = document.createElement("catalog")
document.appendChild(root)

book = document.createElement("book")
book.setAttribute("id", "klyn")
root.appendChild(book)

book.appendChild(document.createTextNode("Klyn Guide"))
print(XMLSerializer.serialize(document, prettyPrint=true, indent=2))

Safe Tree Mutations

A document accepts at most one root element and one document type, with the document type before the root. Text nodes cannot have children. Invalid insertions or replacements raise DOMException without changing either tree. Nodes from another document must first be imported or adopted.

Inserting a DocumentFragment transfers its children in order and empties the fragment; the fragment itself never becomes a child. The entire insertion is validated before any transfer. replaceChild follows the same rules and returns the removed child.

import klyn.io.xml.dom

document = XMLDocument()
root = document.createElement("catalog")
document.appendChild(root)

fragment = document.createDocumentFragment()
fragment.appendChild(document.createElement("book"))
fragment.appendChild(document.createElement("magazine"))
root.appendChild(fragment)

assert root.childNodes.length == 2
assert fragment.childNodes.length == 0
assert fragment.parentNode is null

DOM vs SAX

DOM is easier to query and mutate, but it keeps the document tree in memory. For large files where you only need a streaming pass, prefer SAX. For configuration files, generated documents, and tree transformations, DOM is usually the simpler model.