I’ve written a utility to merge docx documents in Java. “Merge” as in concatenate/join/append, as opposed to diff/merge (although docx4j does include code to do a diff, if you are looking for that instead).
With the utility, you can take 2 or more Word documents, and join them into one.
Edit Feb 2014. MergeDocx is now part of Plutext’s Docx4j Enterprise Edition.
As Eric White’s blog explained:
This programming task is complicated by the need to keep other parts of the document in sync with the data stored in paragraphs. For example, a paragraph can contain a reference to a comment in the comments part, and if there is a problem with this reference, the document is invalid. You must take care when moving / inserting / deleting paragraphs to maintain ‘referential integrity’ within the document.
With this utility, merging/concatenating documents is as easy as invoking the method:
public WordprocessingMLPackage merge(List<WordprocessingMLPackage> wmlPkgs)
In other words, you pass a list of docx, and get a single new docx back.
Edit March 2014. You can try the MergeDocx and/or MergePptx functionality via the demo webapp.
This utility takes care of the niggly edge cases for you:
You can also use my MergeDocx utility to process a docx which is embedded as an altChunk.
Without this utility, you had to rely on Word to convert the altChunk to normal content.
That meant you had to round trip your docx through Word, before docx4j could create a PDF or HTML out of it.
Now you don’t.
To process the w:altChunk elements in a docx, you invoke:
public WordprocessingMLPackage process(WordprocessingMLPackage srcPackage)
You pass in a docx containg altChunks, and get a new docx back which doesn’t.
But wait a minute .. if you can merge Word documents using this tool, why would you ever put an altChunk (containing a docx, as opposed to HTML) into the docx in the first place?
Ordinarily you wouldn’t, you’d just merge with this tool instead. But there are at least 2 possibilities:
- some upstream process put the altChunk there, and now you want to process it in docx4j
- OpenDoPE. The Open Document Processing Ecosystem convention is being extended in a v2.3 to allow other documents to be injected, and a natural thing is to convert an injection instruction to an altChunk. Edit Feb 2014: docx4j 3.0.1 can also bind an XML element containing a base64 encoded docx, inserting it into the docx as an AltChunk. MergeDocx can then convert that content into “real” docx content, suitable for including in a table of contents, or generating HTML or PDF. The binding is two-way, so user edits in Word can be injected back into the XML (eg for persisting to a database).
There is one place my code differs significantly from how Word processes an altChunk, and that is in section handling. When Word processes an altChunk, it seems to largely remove sectPr. So for example, columns will disappear. But it also might merge headers, so the resulting header contains stuff from the headers of both documents! My code doesn’t do that: by default, it includes each section, and headers go with sections.