Ootempl.Replacement (ootempl v0.3.0)
Replaces placeholders in Word XML text nodes while preserving formatting.
This module handles the core XML manipulation logic for replacing {{variable}}
placeholders with values from data maps. It handles the complexities of Word's
XML structure, including:
- Preserving Word formatting (bold, italic, font, size, color)
- XML-escaping replacement values to prevent corruption
- Unescaping literal
{{and}}sequences to{{and}} - Collecting all errors for batch reporting
Word XML Structure
Word stores text in <w:t> elements within <w:r> (run) elements that carry
formatting:
<w:p> <!-- paragraph -->
<w:r> <!-- run with formatting -->
<w:rPr>...</w:rPr> <!-- run properties (formatting) -->
<w:t>Hello {{name}}</w:t> <!-- text -->
</w:r>
</w:p>Split Placeholders
Word often splits placeholders across multiple <w:t> elements. Documents must be
normalized using Ootempl.Xml.Normalizer before calling this module to ensure
placeholders are consolidated. The main Ootempl.render/3 API handles this
automatically.
Examples
Replacing placeholders in a Word document:
data = %{"name" => "World"}
{:ok, doc} = Ootempl.Xml.parse("<w:p><w:r><w:t>Hello {{name}}</w:t></w:r></w:p>")
{:ok, result} = Ootempl.Replacement.replace_in_document(doc, data)
# result now contains "Hello World"
Summary
Functions
Replaces all placeholders in the document XML with values from the data map.
Types
@type placeholder_error_detail() :: %{ placeholder: String.t(), reason: Ootempl.DataAccess.error_reason() }
@type xml_element() :: Ootempl.Xml.xml_element()
@type xml_node() :: Ootempl.Xml.xml_node()
@type xml_text() :: Ootempl.Xml.xml_text()
Functions
@spec replace_in_document(xml_element(), map(), Ootempl.Filters.registry()) :: {:ok, xml_element()} | {:error, Ootempl.PlaceholderError.t()}
Replaces all placeholders in the document XML with values from the data map.
Processes the entire document tree, replacing placeholders while preserving all formatting. Collects all errors and returns them together for batch reporting.
Note: This function expects the document to already be normalized (split placeholders
merged). Use Ootempl.Xml.Normalizer.normalize/1 first if needed, or use the
high-level Ootempl.render/3 API which handles normalization automatically.
Parameters
xml_element- The root XML element (typically the document root)data- Map containing replacement values (string keys)
Returns
{:ok, modified_xml}- Modified XML with all replacements applied{:error, %PlaceholderError{}}- Struct containing all placeholder resolution errors
Examples
Successful replacement:
import Ootempl.Xml
{:ok, doc} = Ootempl.Xml.parse("<w:p><w:r><w:t>{{name}}</w:t></w:r></w:p>")
Ootempl.Replacement.replace_in_document(doc, %{"name" => "John"})
# => {:ok, modified_xml}
Missing placeholder:
{:ok, doc} = Ootempl.Xml.parse("<w:p><w:r><w:t>{{missing}}</w:t></w:r></w:p>")
Ootempl.Replacement.replace_in_document(doc, %{})
# => {:error, %Ootempl.PlaceholderError{
# message: "Placeholder {{missing}} could not be resolved",
# placeholders: [%{placeholder: "{{missing}}", reason: {:path_not_found, ["missing"]}}]
# }}