Ootempl.Xml (ootempl v0.3.0)
XML manipulation utilities for working with Erlang's :xmerl library.
This module provides Elixir-friendly wrappers around :xmerl record structures,
enabling type-safe XML operations for parsing and manipulating Office Open XML document XML.
Record Structures
Defines Elixir records for the following :xmerl types:
:xmlElement- XML element nodes:xmlAttribute- XML attribute nodes:xmlText- XML text content nodes
Parsing and Serialization
Parse XML strings into :xmerl record structures:
{:ok, doc} = Ootempl.Xml.parse("<root><child>text</child></root>")Serialize :xmerl records back to XML strings:
{:ok, xml_string} = Ootempl.Xml.serialize(doc)Round-trip parsing and serialization (useful for testing):
{:ok, xml_string} = Ootempl.Xml.round_trip("<root><child>text</child></root>")All parsing and serialization functions handle XML namespaces correctly, which is essential for .docx files that use namespaces extensively (w:, r:, etc.).
Usage
To use the record macros in your code, you need to import them:
import Ootempl.Xml
element = xmlElement(name: :div, content: [])
name = element_name(element) # Returns "div"See the test suite for comprehensive usage examples.
Summary
Functions
Parses an XML string into :xmerl record structures.
Removes a list of nodes from an XML element.
Serializes :xmerl record structures back to an XML string.
Types
@type xml_attribute() :: tuple()
@type xml_element() :: tuple()
@type xml_node() :: xml_element() | xml_text()
@type xml_text() :: tuple()
Functions
@spec parse(String.t()) :: {:ok, xml_element()} | {:error, term()}
Parses an XML string into :xmerl record structures.
Uses :xmerl_scan.string/2 with namespace conformant parsing to correctly
handle .docx XML which uses namespaces extensively (w:, r:, etc.).
Returns {:ok, document} on success, or {:error, reason} if parsing fails.
Examples
iex> {:ok, _doc} = Ootempl.Xml.parse("<root><child>text</child></root>")
iex> {:error, _reason} = Ootempl.Xml.parse("<root><unclosed>")
@spec remove_nodes(xml_element(), [xml_node()]) :: xml_element()
Removes a list of nodes from an XML element.
Traverses the element's content and removes all nodes that match
any node in the nodes_to_remove list. This is useful for removing
conditional sections when conditions are false.
Parameters
element- The XML element to processnodes_to_remove- List of nodes to remove from the element
Returns
The modified XML element with the specified nodes removed.
Examples
iex> {:ok, doc} = Ootempl.Xml.parse("<root><p>keep</p><p>remove</p></root>")
iex> [_keep, remove] = Ootempl.Xml.find_elements(doc, :p)
iex> modified = Ootempl.Xml.remove_nodes(doc, [remove])
iex> Ootempl.Xml.find_elements(modified, :p) |> length()
1
@spec serialize(xml_element()) :: {:ok, String.t()} | {:error, term()}
Serializes :xmerl record structures back to an XML string.
Uses :xmerl.export_simple/2 to convert the internal representation back
to XML, preserving namespaces and attributes.
Returns {:ok, xml_string} on success, or {:error, reason} if serialization fails.
Examples
iex> {:ok, doc} = Ootempl.Xml.parse("<root><child>text</child></root>")
iex> Ootempl.Xml.serialize(doc)
{:ok, "<?xml version=..."}