package carlo; /** * Created by User on 29/09/2017. */ import com.topologi.diffx.Docx4jDriver; import org.docx4j.Docx4J; import org.docx4j.XmlUtils; import org.docx4j.convert.out.FOSettings; import org.docx4j.diff.Differencer; import org.docx4j.fonts.IdentityPlusMapper; import org.docx4j.openpackaging.exceptions.InvalidFormatException; import org.docx4j.openpackaging.packages.WordprocessingMLPackage; import org.docx4j.openpackaging.parts.Part; import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPart; import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart; import org.docx4j.openpackaging.parts.relationships.Namespaces; import org.docx4j.openpackaging.parts.relationships.RelationshipsPart; import org.docx4j.relationships.Relationship; import org.docx4j.wml.Body; import org.docx4j.wml.Document; import org.w3c.dom.NodeList; import javax.xml.bind.JAXBElement; import java.io.File; import java.io.OutputStream; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.Map; public class CompareDocx1 { private static boolean DOCX_SAVE = true; private static boolean PDF_SAVE = true; private static boolean DIVIDE_AND_CONQUER = true; public static void main(String[] args) { try { System.out.println("***** START"); String newFile = System.getProperty("user.dir") + "/611_2.docx"; String oldFile = System.getProperty("user.dir") + "/611_1.docx"; String newFileTmp = System.getProperty("user.dir") + "/newFileTmp.docx"; String oldFileTmp = System.getProperty("user.dir") + "/oldFileTmp.docx"; WordprocessingMLPackage newerPackage = WordprocessingMLPackage.load(new File(newFile)); MainDocumentPart newerDocumentPart = newerPackage.getMainDocumentPart(); WordprocessingMLPackage olderPackage = WordprocessingMLPackage.load(new File(oldFile)); MainDocumentPart olderDocumentPart = olderPackage.getMainDocumentPart(); /* */ newerPackage.getMainDocumentPart().addParagraphOfText(""); olderPackage.getMainDocumentPart().addParagraphOfText(""); newerPackage.save(new File(newFileTmp)); olderPackage.save(new File(oldFileTmp)); newerPackage = WordprocessingMLPackage.load(new File(newFileTmp)); olderPackage = WordprocessingMLPackage.load(new File(oldFileTmp)); /* */ Body newerBody = (newerPackage.getMainDocumentPart().getJaxbElement()).getBody(); Body olderBody = (olderPackage.getMainDocumentPart().getJaxbElement()).getBody(); List newerL = newerBody.getContent(); org.w3c.dom.Document newerBodyDocument = XmlUtils.marshaltoW3CDomDocument(newerBody); NodeList newerNL = newerBodyDocument.getChildNodes(); List olderL = olderBody.getContent(); org.w3c.dom.Document olderBodyDocument = XmlUtils.marshaltoW3CDomDocument(olderBody); NodeList olderNL = olderBodyDocument.getChildNodes(); System.out.println("Differencing.."); // 2. Do the differencing java.io.StringWriter sw = new java.io.StringWriter(); javax.xml.transform.stream.StreamResult result = new javax.xml.transform.stream.StreamResult(sw); Calendar changeDate = Calendar.getInstance(); Differencer pd = null; if (DIVIDE_AND_CONQUER) { Docx4jDriver.diff(XmlUtils.marshaltoW3CDomDocument(newerBody).getDocumentElement(), XmlUtils.marshaltoW3CDomDocument(olderBody).getDocumentElement(), sw); } else { pd = new Differencer(); pd.diff(newerBody, olderBody, result, "someone", changeDate, newerPackage.getMainDocumentPart().getRelationshipsPart(), olderPackage.getMainDocumentPart().getRelationshipsPart() ); } // 3. Get the result String contentStr = sw.toString(); Body newBody = (Body) XmlUtils.unwrap(XmlUtils.unmarshalString(contentStr)); // 4. Display the result as a PDF // To do this, we'll replace the body in the newer document ((Document) newerPackage.getMainDocumentPart().getJaxbElement()).setBody(newBody); if (DIVIDE_AND_CONQUER) { // No image support at present } else { handleRels(pd, newerPackage.getMainDocumentPart()); } if (DOCX_SAVE) { newerPackage.save(new File(System.getProperty("user.dir") + "/OUT_CompareDocuments.docx")); } if (PDF_SAVE) { newerPackage.setFontMapper(new IdentityPlusMapper()); boolean saveFO = false; String outputfilepath = System.getProperty("user.dir") + "/OUT_CompareDocuments.pdf"; // FO exporter setup (required) // .. the FOSettings object FOSettings foSettings = Docx4J.createFOSettings(); if (saveFO) { foSettings.setFoDumpFile(new java.io.File(System.getProperty("user.dir") + "/OUT_CompareDocuments..fo")); } foSettings.setWmlPackage(newerPackage); // Document format: // The default implementation of the FORenderer that uses Apache Fop will output // a PDF document if nothing is passed via // foSettings.setApacheFopMime(apacheFopMime) // apacheFopMime can be any of the output formats defined in org.apache.fop.apps.MimeConstants or // FOSettings.INTERNAL_FO_MIME if you want the fo document as the result. // exporter writes to an OutputStream. OutputStream os = new java.io.FileOutputStream(outputfilepath); //Don't care what type of exporter you use Docx4J.toFO(foSettings, os, Docx4J.FLAG_NONE); System.out.println("Saved " + System.getProperty("user.dir") + "/OUT_CompareDocuments.pdf"); } } catch (Exception e) { e.printStackTrace(); } } /** * In the general case, you need to handle relationships. * Although not necessary in this simple example, * we do it anyway for the purposes of illustration. * * @throws InvalidFormatException */ private static void handleRels(Differencer pd, MainDocumentPart newMDP) throws InvalidFormatException { RelationshipsPart rp = newMDP.getRelationshipsPart(); // Since we are going to add rels appropriate to the docs being // compared, for neatness and to avoid duplication // (duplication of internal part names is fatal in Word, // and export xslt makes images internal, though it does avoid duplicating // a part ), // remove any existing rels which point to images List relsToRemove = new ArrayList(); for (Relationship r : rp.getRelationships().getRelationship()) { // Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" if (r.getType().equals(Namespaces.IMAGE)) { relsToRemove.add(r); } } for (Relationship r : relsToRemove) { rp.removeRelationship(r); } // Now add the rels we composed Map newRels = pd.getComposedRels(); for (Relationship nr : newRels.keySet()) { if (nr.getTargetMode() != null && nr.getTargetMode().equals("External")) { newMDP.getRelationshipsPart().getRelationships().getRelationship().add(nr); } else { Part part = newRels.get(nr); if (part == null) { System.out.println("ERROR! Couldn't find part for rel " + nr.getId() + " " + nr.getTargetMode()); } else { if (part instanceof BinaryPart) { // ensure contents are loaded, before moving to new pkg ((BinaryPart) part).getBuffer(); } // newMDP.addTargetPart(part, RelationshipsPart.AddPartBehaviour.RENAME_IF_NAME_EXISTS, nr.getId()); newMDP.addTargetPart(part, RelationshipsPart.AddPartBehaviour.OVERWRITE_IF_NAME_EXISTS, nr.getId()); } } } } }