/** * Use an XSLT to alter the contents of this package. The output of the transformation must be * valid pck:package/pck:part format, as emitted by Word 2007. * * @param is * @param transformParameters * @throws Exception */ public void transform(Templates xslt, Map<String, Object> transformParameters) throws Exception { // Prepare in the input document FlatOpcXmlCreator worker = new FlatOpcXmlCreator(this); org.docx4j.xmlPackage.Package pkg = worker.get(); JAXBContext jc = Context.jcXmlPackage; Marshaller marshaller = jc.createMarshaller(); org.w3c.dom.Document doc = org.docx4j.XmlUtils.neww3cDomDocument(); marshaller.marshal(pkg, doc); // javax.xml.bind.util.JAXBResult result = new javax.xml.bind.util.JAXBResult(jc ); // Use constructor which takes Unmarshaller, rather than JAXBContext, // so we can set JaxbValidationEventHandler Unmarshaller u = jc.createUnmarshaller(); u.setEventHandler(new org.docx4j.jaxb.JaxbValidationEventHandler()); javax.xml.bind.util.JAXBResult result = new javax.xml.bind.util.JAXBResult(u); // Perform the transformation org.docx4j.XmlUtils.transform(doc, xslt, transformParameters, result); // javax.xml.bind.JAXBElement je = (javax.xml.bind.JAXBElement)result.getResult(); // org.docx4j.xmlPackage.Package wmlPackageEl = (org.docx4j.xmlPackage.Package)je.getValue(); org.docx4j.xmlPackage.Package wmlPackageEl = (org.docx4j.xmlPackage.Package) XmlUtils.unwrap(result.getResult()); org.docx4j.convert.in.FlatOpcXmlImporter xmlPackage = new org.docx4j.convert.in.FlatOpcXmlImporter(wmlPackageEl); ContentTypeManager ctm = new ContentTypeManager(); Part tmpDocPart = xmlPackage.getRawPart(ctm, "/word/document.xml", null); Part tmpStylesPart = xmlPackage.getRawPart(ctm, "/word/styles.xml", null); // This code assumes all the existing rels etc of // the existing main document part are still relevant. // if (wmlDocument==null) { // log.warn("Couldn't get main document part from package transform result!"); // } else { // this.getMainDocumentPart().setJaxbElement(wmlDocument); // } this.getMainDocumentPart() .setJaxbElement(((JaxbXmlPart<Document>) tmpDocPart).getJaxbElement()); // // if (wmlStyles==null) { // log.warn("Couldn't get style definitions part from package transform result!"); // } else { // this.getMainDocumentPart().getStyleDefinitionsPart().setJaxbElement(wmlStyles); // } this.getMainDocumentPart() .getStyleDefinitionsPart(true) .setJaxbElement(((JaxbXmlPart<Styles>) tmpStylesPart).getJaxbElement()); }
public static void apply(WordprocessingMLPackage otherPackage, Alterations alterations) throws Docx4JException, JAXBException { if (alterations.getContentTypes() != null) { log.info("replacing [Content_Types].xml"); ContentTypeManager newCTM = new ContentTypeManager(); newCTM.parseContentTypesFile(new ByteArrayInputStream(alterations.getContentTypes())); otherPackage.setContentTypeManager(newCTM); } if (alterations.isEmpty()) return; // -- Deletions List<PartName> removedParts = new ArrayList<PartName>(); for (Alteration a : alterations.getPartsDeleted()) { org.docx4j.xmlPackage.Part xmlpart = a.getPart(); // These deleted parts are likely to be attached to // to otherPackage, but there is no requirement for // that to be so. In other words, you could try // to apply the alterations to some third docx. // It might have already been deleted as a consequence // of recursive deletion... if (removedParts.contains(xmlpart.getName())) continue; // Design decision: how to find owning rels part? // Since part might not be from this package, can't do: // part.getOwningRelationshipPart().removePart(p.getPartName()) // We could store the info when AlteredParts is run, // but lets try to get away without that... // If a part has been deleted, we know its owning rels will // have been modified or deleted. So look for that. // BUT IT WON'T BE THERE IF ITS BEEN DELETED! DOH! // So we have to store the info when AlteredParts is run // after all. Part parentPart = otherPackage.getParts().get(a.getSourcePartName()); if (a.getPart().getContentType().equals(ContentTypes.RELATIONSHIPS_PART)) { parentPart.setRelationships(null); } else { removedParts.addAll( parentPart.getRelationshipsPart().removePart(new PartName(xmlpart.getName()))); } } // -- Modifications for (Alteration a : alterations.getPartsModified()) { log.info("Applying modifications to part: " + a.getPart().getName()); if (a.getPart().getContentType().equals(ContentTypes.RELATIONSHIPS_PART)) { RelationshipsPart newRP = null; // FlatOpcXmlImporter.createRelationshipsPart(a.getPart()); if (a.getSourcePartName().equals("/")) { newRP = otherPackage.getRelationshipsPart(true); // otherPackage.setRelationships(newRP); // newRP.setSourceP(otherPackage); } else { Part parentPart = otherPackage.getParts().get(a.getSourcePartName()); newRP = parentPart.getRelationshipsPart(true); // parentPart.setRelationships(newRP); // newRP.setSourceP(parentPart); } FlatOpcXmlImporter.populateRelationshipsPart(newRP, a.getPart().getXmlData().getAny()); } else { Part targetPart = otherPackage.getParts().get(new PartName(a.getPart().getName())); if (targetPart == null) { log.error( "Couldn't find " + a.getPart().getName() + " @ " + a.getSourcePartName().getName()); continue; } Part tmpPart = FlatOpcXmlImporter.getRawPart(otherPackage.getContentTypeManager(), a.getPart(), null); if (targetPart instanceof JaxbXmlPart) { ((JaxbXmlPart) targetPart).setJaxbElement(((JaxbXmlPart) tmpPart).getJaxbElement()); } else if (targetPart instanceof XmlPart) { ((XmlPart) targetPart).setDocument(((XmlPart) tmpPart).getDocument()); } else if (targetPart instanceof CustomXmlDataStoragePart) { ((CustomXmlDataStoragePart) targetPart) .setData(((CustomXmlDataStoragePart) tmpPart).getData()); // TODO: check that } else if (targetPart instanceof BinaryPart) { ((BinaryPart) targetPart).setBinaryData(((BinaryPart) tmpPart).getBuffer()); } else { log.error("TODO: handle " + targetPart.getClass().getName()); } } } // -- Additions for (Alteration a : alterations.getPartsAdded()) { log.info("Adding part: " + a.getPart().getName()); if (a.getPart().getContentType().equals(ContentTypes.RELATIONSHIPS_PART)) { RelationshipsPart newRP = null; // FlatOpcXmlImporter.createRelationshipsPart(a.getPart()); if (a.getSourcePartName().equals("/")) { newRP = otherPackage.getRelationshipsPart(true); // otherPackage.setRelationships(newRP); // newRP.setSourceP(otherPackage); } else { Part parentPart = otherPackage.getParts().get(a.getSourcePartName()); newRP = parentPart.getRelationshipsPart(true); // parentPart.setRelationships(newRP); // newRP.setSourceP(parentPart); } FlatOpcXmlImporter.populateRelationshipsPart(newRP, a.getPart().getXmlData().getAny()); } else { Part parentPart = otherPackage.getParts().get(a.getSourcePartName()); Part newPart = FlatOpcXmlImporter.getRawPart(otherPackage.getContentTypeManager(), a.getPart(), null); // There will already be a rel for the new part, // since we will already have modified or added the rels part // so don't do AddTargetPart (which will probably create a new rel id, // which will cause problems) newPart.setOwningRelationshipPart(parentPart.getRelationshipsPart()); newPart .getSourceRelationships() .add(parentPart.getRelationshipsPart().getRel(new PartName(a.getPart().getName()))); otherPackage.getParts().put(newPart); newPart.setPackage(otherPackage); // TODO: add content type if necessary } } }