toolgarden.xyz
中文
browser tool developmentOpen XMLDOCX mergePPTX mergedocument engineering

How to Merge Word and PowerPoint Files in the Browser with Open XML

Merge DOCX and PPTX without Office automation by unpacking Open XML ZIP packages, copying relationship graphs, resolving part collisions, and rebuilding valid documents.

ToolGarden tools prioritize browser-local processing, so files and text do not need to be uploaded to a server.

Published July 22, 202614 min readBy ToolGarden

DOCX and PPTX files are ZIP packages containing XML parts, media, and relationship graphs. That makes browser merging possible without Microsoft Office, but it also means concatenating document.xml or copying slide XML alone is not enough.

A correct merger must unzip each package, preserve order, allocate new relationship IDs, recursively copy images and dependent parts, rewrite relative targets, resolve filename collisions, update content types, and zip the result with the original Office MIME type.

Read Office files as package graphs

Open XML parts are connected by .rels files. A Word body can reference images, hyperlinks, numbering, headers, or embedded objects. A PowerPoint slide can reference a layout, master, theme, chart, notes, and media. Relationship targets are relative to the part that owns them.

The package root also contains [Content_Types].xml, which tells Office how to interpret extensions and individual parts. Every copied destination part must retain an appropriate default or override content type.

Package concernWord examplePowerPoint example
Main contentword/document.xmlppt/presentation.xml
Ordered unitsBody blocksp:sldId list
Relationshipsword/_rels/document.xml.relsppt/_rels/presentation.xml.rels
Dependent contentImages, headers, stylesSlides, layouts, themes, media

Build a reusable recursive part copier

Given a source part and destination path, copy its bytes, copy its content type, parse its relationship file, and recursively copy every internal target. External links stay external. If the desired path already exists, allocate a merged suffix and rewrite the relationship target relative to the new owner part.

Cache source-to-destination mappings during one import so shared layouts or media are copied once. A used-path set prevents two imports from claiming the same destination.

function copyPart(sourcePath: string, destinationPath: string) {
  destinationZip[destinationPath] = sourceZip[sourcePath];
  copyContentType(sourcePath, destinationPath);

  for (const relationship of readRelationships(sourcePath)) {
    if (relationship.targetMode === 'External') continue;

    const sourceTarget = resolveTarget(sourcePath, relationship.target);
    const destinationTarget = uniquePartPath(sourceTarget);
    copyPart(sourceTarget, destinationTarget);
    relationship.target = relativePath(destinationPath, destinationTarget);
  }

  writeRelationships(destinationPath, relationships);
}

Merge Word bodies and rewrite relationship IDs

Use the first DOCX as the base package. Split its w:body from the surrounding document XML, remove section properties from intermediate bodies, and insert an explicit page break before each imported document. The final base section properties remain at the end.

For every source document relationship, allocate a new rId in the base list, copy the target graph, and replace r:id, r:embed, r:link, or o:relid references inside the imported body. Without this rewrite, an image can point to another document’s unrelated relationship.

const base = unzipSync(await bytes(files[0]));
const bodyParts = [withoutSectionProperties(readWordBody(base))];

for (const file of files.slice(1)) {
  const source = unzipSync(await bytes(file));
  let body = withoutSectionProperties(readWordBody(source));

  for (const relationship of readDocumentRelationships(source)) {
    const nextId = getNextRelationshipId(baseRelationships);
    copyRelatedPartRecursively(relationship);
    body = replaceRelationshipReferences(body, relationship.id, nextId);
  }

  bodyParts.push(pageBreakXml(), body);
}

writeWordBody(base, bodyParts.join(''));
return zipSync(base);

Merge PowerPoint by slide order, not filenames

Slide filenames are not the authoritative order. Read p:sldId entries from presentation.xml, resolve each r:id through presentation relationships, and only fall back to numeric slide filenames when the order list is unavailable.

Assign a new slide part index, recursively copy the slide and dependencies, create a new presentation relationship, and append a p:sldId with an unused numeric ID. This preserves source order while avoiding collisions with existing slides.

  • Copy layouts, masters, themes, charts, notes, and media through relationships.
  • Preserve external hyperlinks without trying to package their targets.
  • Update [Content_Types].xml after all copied parts.
  • Count slides again from the rebuilt package before reporting success.

Why regex is acceptable only at controlled boundaries

This implementation uses targeted XML extraction and attribute rewriting for known Open XML structures. It is compact and browser-friendly, but regex is not a general XML parser. Namespace variations, unusual formatting, malformed packages, macros, signatures, and advanced Office features can exceed those assumptions.

Validate expected main parts before modifying a package, keep transformations narrow, and open generated fixtures in multiple Office viewers. For high-fidelity enterprise merging, use a complete Open XML library or a server environment with Office-grade tooling.

Security, limits, and output validation

ZIP packages can expand far beyond their compressed size. Limit file count, compressed bytes, and extracted entry count, and be alert to zip bombs. Do not execute macros or fetch external relationships while merging.

A successful zip operation does not prove Office will accept the file. Verify required parts, relationship targets, content types, slide or body counts, and then open representative output in Word, PowerPoint, LibreOffice, and a web viewer.

Key takeaways

Browser Office merging works because DOCX and PPTX are package graphs, not opaque binaries. The reusable core is recursive relationship copying with collision-safe paths and content types; Word then merges bodies and rIds, while PowerPoint appends ordered slide relationships. Treat output validation as part of the algorithm.

Frequently asked questions

Q.Why not concatenate DOCX XML bodies and stop there?

Imported body elements reference relationship IDs for images, links, and other parts. Those IDs belong to the source package and can collide or point nowhere in the destination unless relationships and dependent files are copied and rewritten.

Q.Why can a PowerPoint slide depend on many other files?

A slide commonly references its layout, which references a master and theme, plus images, charts, notes, and embedded data. Copying the slide XML alone produces missing visuals or an invalid deck.

Q.Does browser merging preserve every Office feature?

No implementation should promise that without exhaustive compatibility work. Macros, signatures, advanced fields, custom XML, embedded objects, comments, and unusual namespace structures need dedicated handling and tests.

Q.Are DOCX and PPTX really ZIP files?

Yes. They follow the Open Packaging Conventions: XML and binary parts are stored in a ZIP container and connected through relationship files and content-type declarations.