Replace text in a Word document using streaming XML

Streaming replacement is useful for large documents because the main document XML can be processed without loading a full model in memory.

The tradeoff is the same as other large-part workflows: a DOM-style reader is easier to query and edit, but it materializes the part; a streaming reader processes XML forward-only and can use much less memory.

Rust workflow

Open the main document part, stream across text elements, and replace matches inside each w:t value:

#![allow(unused)]
fn main() {
pub fn replace_text_in_main_document(
  path: &Path,
  search: &str,
  replacement: &str,
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
  let mut document = WordprocessingDocument::new_from_file_with_settings(path, lazy_settings())?;
  let main_part = document.main_document_part()?;
  let document_xml = main_part.data_as_str(&document)?.unwrap_or_default();
  let updated_xml = replace_text_values(document_xml, search, replacement);

  main_part.set_data(&mut document, updated_xml.into_bytes())?;

  let mut buffer = Cursor::new(Vec::new());
  document.save(&mut buffer)?;
  Ok(buffer.into_inner())
}
}

The upstream streaming pattern reads the main document part and writes updated XML to a separate in-memory stream, then replaces the original part after both reader and writer are closed. This avoids opening the same part for simultaneous read and write streams.

Text in a Word document can be split across multiple w:t elements. Single-word replacement is straightforward; phrase replacement needs a buffering strategy that spans runs while preserving run properties.