/* * Copyright 2007, Plutext Pty Ltd. * * This file is part of Docx4all. Docx4all is free software: you can redistribute it and/or modify it under the terms of version 3 of the GNU General Public License as published by the Free Software Foundation. Docx4all is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Docx4all. If not, see <http://www.gnu.org/licenses/>. */ package org.docx4all.util; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.StringReader; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.text.AttributeSet; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.namespace.QName; import javax.xml.transform.Source; import javax.xml.transform.Templates; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.stream.StreamSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.docx4all.ui.main.Constants; import org.docx4all.xml.ElementML; import org.docx4all.xml.ElementMLIterator; import org.docx4all.xml.ObjectFactory; import org.docx4all.xml.ParagraphML; import org.docx4all.xml.PropertiesContainerML; import org.docx4all.xml.RunContentML; import org.docx4all.xml.RunML; import org.docx4j.XmlUtils; import org.docx4j.convert.out.flatOpcXml.FlatOpcXmlCreator; import org.docx4j.diff.Differencer; import org.docx4j.jaxb.Context; import org.docx4j.jaxb.NamespacePrefixMapperUtils; import org.docx4j.openpackaging.contenttype.ContentTypeManager; import org.docx4j.openpackaging.exceptions.InvalidFormatException; import org.docx4j.openpackaging.packages.WordprocessingMLPackage; import org.docx4j.openpackaging.parts.DocPropsCustomPart; import org.docx4j.openpackaging.parts.JaxbXmlPart; import org.docx4j.openpackaging.parts.Part; import org.docx4j.openpackaging.parts.relationships.RelationshipsPart; import org.docx4j.wml.SdtBlock; import org.docx4j.wml.SdtContentBlock; import org.plutext.transforms.Changesets.Changeset; import org.w3c.dom.Node; /** * @author Jojada Tirtowidjojo - 04/01/2008 */ public class XmlUtil { private final static SimpleDateFormat RFC3339_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); protected static Logger log = LoggerFactory.getLogger(XmlUtil.class); /** * Serialise the WordprocessingMLPackage in pkg:package format * * @param wmlPackage * @param out */ public final static void serialize(WordprocessingMLPackage wmlPackage, OutputStream out) { try { FlatOpcXmlCreator worker = new FlatOpcXmlCreator(wmlPackage); org.docx4j.xmlPackage.Package pkg = worker.get(); JAXBContext jc = Context.jcXmlPackage; Marshaller marshaller=jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); // Use the character set expected by JEditorPane //marshaller.setProperty(Marshaller.JAXB_ENCODING, "ISO-10646-UCS-2"); marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-16"); // Suppress the XML declaration marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true); NamespacePrefixMapperUtils.setProperty(marshaller, NamespacePrefixMapperUtils.getPrefixMapper()); /* Setting the property as above is all you need to do for the code * to compile in Eclipse (or using Ant on the Mac with Apple's Java 6 preview). * * However if you try to compile it using javac (eg via Ant), you may get: * * [javac] /home/dev/workspace/docx4all/src/org/docx4all/util/XmlUtil.java:108: cannot access com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper * [javac] class file for com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper not found * * To get around this, see * Step 4 in http://pragmaticintegration.blogspot.com/2007/11/moving-jaxb-20-applications-built-by.html * * The workaround is to add bootclasspathref="jre.libs" includeJavaRuntime="yes" to the javac task, * which I have done. * */ marshaller.marshal(pkg, out); } catch (Exception exc) { exc.printStackTrace(); throw new RuntimeException(exc); } } /** * Deserialise the inputstream from pkg:package format * into a WordprocessingMLPackage. * * @param wmlPackage * @param in */ public final static WordprocessingMLPackage deserialize( WordprocessingMLPackage wmlPackage, InputStream in) { // NB at present we only handle main document part and style part. try { JAXBContext jc = Context.jcXmlPackage; Unmarshaller u = jc.createUnmarshaller(); u.setEventHandler(new org.docx4j.jaxb.JaxbValidationEventHandler()); javax.xml.bind.JAXBElement je = (javax.xml.bind.JAXBElement)u.unmarshal( new javax.xml.transform.stream.StreamSource(in)); org.docx4j.xmlPackage.Package wmlPackageEl = (org.docx4j.xmlPackage.Package)je.getValue(); 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); // org.docx4j.wml.Document wmlDocument = null; // org.docx4j.wml.Styles wmlStyles = null; // for (org.docx4j.wml.Package.Part p : wmlPackageEl.getPart() ) { // // if (p.getXmlData().getDocument()!= null) { // wmlDocument = p.getXmlData().getDocument(); // } // if (p.getXmlData().getStyles()!= null) { // wmlStyles = p.getXmlData().getStyles(); // } // } if (wmlPackage == null) { wmlPackage = ObjectFactory.createDocumentPackage( (org.docx4j.wml.Document)((JaxbXmlPart)tmpDocPart).getJaxbElement()); } else { wmlPackage.getMainDocumentPart().setJaxbElement( (org.docx4j.wml.Document)((JaxbXmlPart)tmpDocPart).getJaxbElement()); } // That handled the Main Document Part; now set the Style part. wmlPackage.getMainDocumentPart().getStyleDefinitionsPart().setJaxbElement( (org.docx4j.wml.Styles)((JaxbXmlPart)tmpStylesPart).getJaxbElement() ); } catch (Exception exc) { exc.printStackTrace(); throw new RuntimeException(exc); } return wmlPackage; } public final static String getEnclosingTagPair(QName qname) { return getEnclosingTagPair(qname.getPrefix(), qname.getLocalPart()); } public final static String getEnclosingTagPair(Node node) { return getEnclosingTagPair(node.getPrefix(), node.getLocalName()); } private final static String getEnclosingTagPair(String prefix, String localName) { if (prefix == null) { prefix = ""; } else if (prefix.length() > 0) { prefix = prefix + ":"; } StringBuffer sb = new StringBuffer(); sb.append("<"); sb.append(prefix); sb.append(localName); sb.append(">"); sb.append("</"); sb.append(prefix); sb.append(localName); sb.append(">"); return sb.toString(); } /** * * Filters out certain features of WordprocessingML which docx4all cannot yet handle, * into something it can. Examples include proofErr, hyperlink, and lastRenderedPageBreak. * * @param wmlPackage */ public final static WordprocessingMLPackage applyFilter(WordprocessingMLPackage wmlPackage) { try { // Apply the filter WordprocessingMLPackage.FilterSettings filterSettings = new WordprocessingMLPackage.FilterSettings(); filterSettings.setRemoveProofErrors(true); filterSettings.setRemoveContentControls(false); filterSettings.setRemoveRsids(true); filterSettings.setTidyForDocx4all(true); wmlPackage.filter(filterSettings); } catch (Exception exc) { exc.printStackTrace(); throw new RuntimeException(exc); } return wmlPackage; } public final static org.docx4j.docProps.custom.Properties.Property getCustomProperty(WordprocessingMLPackage wmlPackage, String propertyName) { org.docx4j.docProps.custom.Properties.Property theProp = null; DocPropsCustomPart docPropsCustomPart = wmlPackage.getDocPropsCustomPart(); org.docx4j.docProps.custom.Properties customProps = (org.docx4j.docProps.custom.Properties) docPropsCustomPart.getJaxbElement(); List<org.docx4j.docProps.custom.Properties.Property> list = (customProps != null) ? customProps.getProperty() : null; if (list != null) { for (org.docx4j.docProps.custom.Properties.Property temp: list) { String s = temp.getName(); if (propertyName.equals(s)) { theProp = temp; break; } } } return theProp; } public final static boolean isSharedDocumentPackage(WordprocessingMLPackage wmlPackage) { org.docx4j.docProps.custom.Properties.Property groupingProp = getCustomProperty( wmlPackage, Constants.PLUTEXT_GROUPING_PROPERTY_NAME); org.docx4j.docProps.custom.Properties.Property checkinProp = getCustomProperty( wmlPackage, Constants.PLUTEXT_CHECKIN_MESSAGE_ENABLED_PROPERTY_NAME); return (groupingProp != null && checkinProp != null); } public final static WordprocessingMLPackage createNewPackage( WordprocessingMLPackage source, boolean copyMainDocumentPart, boolean copyStyleDefPart, boolean copyDocPropsCustomPart) throws InvalidFormatException { // Create a package WordprocessingMLPackage thePack = new WordprocessingMLPackage(); //Check for source's document part org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart srcDocumentPart = source.getMainDocumentPart(); if (srcDocumentPart == null) { log.warn("createNewPackage(): Main document part missing!"); } else { // Create main document part org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart documentPart = new org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart(); Object jaxbElement; if (copyMainDocumentPart) { jaxbElement = org.docx4j.XmlUtils.deepCopy(srcDocumentPart.getJaxbElement()); } else if (isSharedDocumentPackage(source)) { jaxbElement = ObjectFactory.createEmptySharedDocument(); } else { jaxbElement = ObjectFactory.createEmptyDocument(); } documentPart.setJaxbElement((org.docx4j.wml.Document)jaxbElement); thePack.addTargetPart(documentPart); //Check for source's styles part JaxbXmlPart srcStylesPart = srcDocumentPart.getStyleDefinitionsPart(); if (srcStylesPart == null) { log.warn("createNewPackage(): Style definitions part missing!"); } else { // Create a styles part org.docx4j.openpackaging.parts.WordprocessingML.StyleDefinitionsPart stylesPart = new org.docx4j.openpackaging.parts.WordprocessingML.StyleDefinitionsPart(); if (copyStyleDefPart) { jaxbElement = org.docx4j.XmlUtils.deepCopy(srcStylesPart.getJaxbElement()); stylesPart.setJaxbElement( (org.docx4j.wml.Styles)jaxbElement); // Add the styles part to the main document part relationships // (creating it if necessary) documentPart.addTargetPart(stylesPart); // NB - add it to main doc part, not package! } else { try { stylesPart.unmarshalDefaultStyles(); // Add the styles part to the main document part relationships // (creating it if necessary) documentPart.addTargetPart(stylesPart); // NB - add it to main doc part, not package! } catch (JAXBException exc) { ;//ignore } } } //Check for document custom properties DocPropsCustomPart docPropsCustomPart = thePack.getDocPropsCustomPart(); if (copyDocPropsCustomPart) { DocPropsCustomPart srcDocPropsCustomPart = source.getDocPropsCustomPart(); jaxbElement = org.docx4j.XmlUtils.deepCopy(srcDocPropsCustomPart.getJaxbElement(), Context.jcDocPropsCustom); docPropsCustomPart.setJaxbElement((org.docx4j.docProps.custom.Properties)jaxbElement); } } return thePack; } public final static void setPlutextGroupingProperty( WordprocessingMLPackage wmlPackage, String value) { org.docx4j.openpackaging.parts.DocPropsCustomPart docPropsCustomPart = wmlPackage.getDocPropsCustomPart(); org.docx4j.docProps.custom.Properties customProps = (org.docx4j.docProps.custom.Properties) docPropsCustomPart.getJaxbElement(); org.docx4j.docProps.custom.ObjectFactory factory = new org.docx4j.docProps.custom.ObjectFactory(); //Set plutext:Grouping property org.docx4j.docProps.custom.Properties.Property groupingProp = XmlUtil.getCustomProperty( wmlPackage, Constants.PLUTEXT_GROUPING_PROPERTY_NAME); if (groupingProp == null) { groupingProp = factory.createPropertiesProperty(); groupingProp.setName(Constants.PLUTEXT_GROUPING_PROPERTY_NAME); groupingProp.setFmtid( org.docx4j.openpackaging.parts.DocPropsCustomPart.fmtidValLpwstr); // Magic string groupingProp.setPid(customProps.getNextId()); customProps.getProperty().add(groupingProp); } groupingProp.setLpwstr(value); } public final static void setPlutextCheckinMessageEnabledProperty( WordprocessingMLPackage wmlPackage, boolean enabled) { org.docx4j.openpackaging.parts.DocPropsCustomPart docPropsCustomPart = wmlPackage.getDocPropsCustomPart(); org.docx4j.docProps.custom.Properties customProps = (org.docx4j.docProps.custom.Properties) docPropsCustomPart.getJaxbElement(); org.docx4j.docProps.custom.ObjectFactory factory = new org.docx4j.docProps.custom.ObjectFactory(); org.docx4j.docProps.custom.Properties.Property checkinProp = XmlUtil.getCustomProperty( wmlPackage, Constants.PLUTEXT_CHECKIN_MESSAGE_ENABLED_PROPERTY_NAME); if (checkinProp == null) { checkinProp = factory.createPropertiesProperty(); checkinProp.setName(Constants.PLUTEXT_CHECKIN_MESSAGE_ENABLED_PROPERTY_NAME); checkinProp.setFmtid( org.docx4j.openpackaging.parts.DocPropsCustomPart.fmtidValLpwstr); // Magic string checkinProp.setPid(customProps.getNextId()); customProps.getProperty().add(checkinProp); } if (enabled) { checkinProp.setLpwstr(Boolean.TRUE.toString()); } else { checkinProp.setLpwstr(Boolean.FALSE.toString()); } } public final static void removePlutextProperty( WordprocessingMLPackage wmlPackage, String propertyName) { List<String> names = new ArrayList<String>(1); names.add(propertyName); removePlutextProperties(wmlPackage, names); } public final static void removePlutextProperties( WordprocessingMLPackage wmlPackage, List<String> propertyNames) { DocPropsCustomPart docPropsCustomPart = wmlPackage.getDocPropsCustomPart(); org.docx4j.docProps.custom.Properties customProps = (org.docx4j.docProps.custom.Properties) docPropsCustomPart.getJaxbElement(); List<org.docx4j.docProps.custom.Properties.Property> list = customProps.getProperty(); if (list != null) { List<Integer> indexes = new ArrayList<Integer>(); for (int i=0; i < list.size(); i++) { org.docx4j.docProps.custom.Properties.Property prop = list.get(i); if (propertyNames.contains(prop.getName())) { indexes.add(Integer.valueOf(i)); } } for (int i = indexes.size()-1; 0 <= i; i--) { list.remove(indexes.get(i).intValue()); } } } public final static void removeSharedDocumentProperties(WordprocessingMLPackage wmlPackage) { List<String> names = new ArrayList<String>(2); names.add(Constants.PLUTEXT_GROUPING_PROPERTY_NAME); names.add(Constants.PLUTEXT_CHECKIN_MESSAGE_ENABLED_PROPERTY_NAME); removePlutextProperties(wmlPackage, names); } /** * Empty the children of parent argument * * @param parent the element whose children are to be deleted. * @return The deleted children */ public final static List<ElementML> deleteChildren(ElementML parent) { List<ElementML> children = new ArrayList<ElementML>(parent.getChildren()); for (ElementML elem: children) { elem.delete(); } return children; } public final static RunContentML getFirstRunContentML(ElementML root) { RunContentML theElem = null; if (root.getChildrenCount() > 0) { ElementML lastChild = root.getChild(0); if (lastChild instanceof RunContentML) { theElem = (RunContentML) lastChild; } else { theElem = getFirstRunContentML(lastChild); } } else if (root instanceof RunContentML) { theElem = (RunContentML) root; } return theElem; } public final static RunContentML getLastRunContentML(ElementML root) { RunContentML theElem = null; if (root.getChildrenCount() > 0) { ElementML lastChild = root.getChild(root.getChildrenCount() - 1); if (lastChild instanceof RunContentML) { theElem = (RunContentML) lastChild; } else { theElem = getLastRunContentML(lastChild); } } else if (root instanceof RunContentML) { theElem = (RunContentML) root; } return theElem; } public final static int getIteratedIndex(ElementML root, ElementML target) { int theIdx = -1; ElementMLIterator it = new ElementMLIterator(root); int i = -1; while (it.hasNext() && theIdx == -1) { i++; ElementML elem = it.next(); if (elem == target) { theIdx = i; } } return theIdx; } public final static ElementML getElementMLAtIteratedIndex(ElementML root, int idx) { ElementML theElem = null; ElementMLIterator it = new ElementMLIterator(root); int i = -1; while (it.hasNext() && i < idx) { i++; theElem = it.next(); } if (i != idx) { theElem = null; } return theElem; } public final static void deleteIteration(ElementML root, int startIdx, int endIdx) { List<ElementML> list = new ArrayList<ElementML>(); ElementMLIterator it = new ElementMLIterator(root); int i = -1; while (it.hasNext() && i < endIdx) { ElementML ml = it.next(); i++; if (startIdx <= i) { list.add(ml); } } if (!list.isEmpty()) { for (ElementML ml: list) { ml.delete(); } } } public final static void setAttributes( ElementML elem, AttributeSet paragraphAttrs, AttributeSet runAttrs, boolean replace) { ElementMLIterator it = new ElementMLIterator(elem); while (it.hasNext()) { ElementML ml = it.next(); if (runAttrs != null && (ml instanceof RunML)) { PropertiesContainerML prop = ((RunML) ml).getRunProperties(); if (replace) { prop.removeAttributes(prop.getAttributeSet()); } prop.addAttributes(runAttrs); } else if (paragraphAttrs != null && (ml instanceof ParagraphML)) { PropertiesContainerML prop = ((ParagraphML) ml).getParagraphProperties(); if (replace) { prop.removeAttributes(prop.getAttributeSet()); } prop.addAttributes(paragraphAttrs); } } } static Templates xsltApplyRemoteChanges; public final static void applyRemoteRevisions( javax.xml.transform.Source src, javax.xml.transform.Result result) { try { if (xsltApplyRemoteChanges == null) { Source xsltSource = new StreamSource( org.docx4j.utils.ResourceUtils .getResource("org/docx4all/util/ApplyRemoteChanges.xslt")); xsltApplyRemoteChanges = XmlUtils .getTransformerTemplate(xsltSource); } org.docx4j.XmlUtils.transform(src, xsltApplyRemoteChanges, null, result); } catch (Exception exc) { exc.printStackTrace(); } } static Templates xsltDiscardRemoteChanges; public final static void discardRemoteRevisions( javax.xml.transform.Source src, javax.xml.transform.Result result) { try { if (xsltDiscardRemoteChanges == null) { Source xsltSource = new StreamSource( org.docx4j.utils.ResourceUtils .getResource("org/docx4all/util/DiscardRemoteChanges.xslt")); xsltDiscardRemoteChanges = XmlUtils .getTransformerTemplate(xsltSource); } org.docx4j.XmlUtils.transform(src, xsltDiscardRemoteChanges, null, result); } catch (Exception exc) { exc.printStackTrace(); } } static Templates xsltExport; public final static WordprocessingMLPackage export( WordprocessingMLPackage source) { WordprocessingMLPackage theResult = null; try { boolean copyMainDocumentPart = true; boolean copyStyleDefPart = true; boolean copyDocPropsCustomPart = false; theResult = createNewPackage(source, copyMainDocumentPart, copyStyleDefPart, copyDocPropsCustomPart); if (xsltExport == null) { Source xsltSource = new StreamSource( org.docx4j.utils.ResourceUtils .getResource("org/docx4all/util/Export.xslt")); xsltExport = XmlUtils.getTransformerTemplate(xsltSource); } theResult.transform(xsltExport, null); } catch (Exception exc) { exc.printStackTrace(); theResult = null; } return theResult; } /* Split a control containing n paragraphs * into n controls. * * The ID of the first control remains the same. * * Returns a list of SdtBlock(s) that represents * all new resulting content controls. */ public final static List<SdtBlock> chunk(SdtBlock cc) { SdtBlock copy = (SdtBlock) XmlUtils.deepCopy(cc); List<SdtBlock> theChunks = new ArrayList<SdtBlock>(); theChunks.add(copy); List<Object> children = copy.getSdtContent().getContent(); if (children.size() > 1) { List<Object> childrenToChunk = new ArrayList<Object>(); for (int i=1; i < children.size(); i++) { Object o = children.get(i); if (o instanceof org.docx4j.wml.P || (o instanceof org.docx4j.wml.Tbl)) { childrenToChunk.add(o); } else { //TODO: Consider what to do with these } } for (Object o: childrenToChunk) { children.remove(o); SdtBlock newChunk = createSdtBlock(); newChunk.getSdtContent().getContent().add(o); theChunks.add(newChunk); } } return theChunks; } private final static SdtBlock createSdtBlock() { org.docx4j.wml.SdtBlock sdtBlock = ObjectFactory.createSdtBlock(); org.docx4j.wml.SdtPr sdtPr = ObjectFactory.createSdtPr(); org.docx4j.wml.SdtContentBlock content = ObjectFactory.createSdtContentBlock(); sdtPr.setId(); sdtPr.setTag(ObjectFactory.createTag("0")); sdtBlock.setSdtPr(sdtPr); sdtBlock.setSdtContent(content); return sdtBlock; } public final static boolean containsTrackedChanges(Object jaxbObject) { String s = org.docx4j.XmlUtils.marshaltoString(jaxbObject, false); return (s.indexOf("</w:ins>") >= 0 || s.indexOf("</w:del>") >= 0); } public final static org.docx4j.wml.SdtBlock markupDifference( org.docx4j.wml.SdtBlock leftSdt, org.docx4j.wml.SdtBlock rightSdt, Changeset changeset) throws Exception { org.docx4j.wml.SdtBlock theSdt = ObjectFactory.createSdtBlock(); theSdt.setSdtPr((org.docx4j.wml.SdtPr) XmlUtils.deepCopy(leftSdt .getSdtPr())); // javax.xml.bind.util.JAXBResult result = // new javax.xml.bind.util.JAXBResult( // org.docx4j.jaxb.Context.jc); 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(); // changeDate.setTime(RFC3339_FORMAT.parse(changeset.getDate())); Calendar changeDate = null; Differencer pd = new Differencer(); pd.diff( (org.docx4j.wml.SdtContentBlock)leftSdt.getSdtContent(), (org.docx4j.wml.SdtContentBlock)rightSdt.getSdtContent(), result, changeset.getModifier(), changeDate, new RelationshipsPart(), new RelationshipsPart() ); // TODO - feed it the correct relationships parts! // SdtContentBlock markedUpContent = (SdtContentBlock) // result.getResult(); String contentStr = sw.toString(); log.info("Transform: " + contentStr); SdtContentBlock markedUpContent = (SdtContentBlock) org.docx4j.XmlUtils .unmarshalString(contentStr); log.debug("..unmarshalled "); // Now put into resulting sdt. theSdt.setSdtContent(markedUpContent); return theSdt; } public final static org.docx4j.wml.SdtBlock markupAsDeletion( org.docx4j.wml.SdtBlock sdt, Changeset changeset) throws Exception { Map<String, Object> params = new HashMap<String, Object>(1); params.put("author", changeset.getModifier()); return markupAsDeletion(sdt, params); } public final static org.docx4j.wml.SdtBlock markupAsDeletion( org.docx4j.wml.SdtBlock sdt, Map<String, Object> xsltParameters) throws Exception { String xml = XmlUtils.marshaltoString(sdt, false); return markupAsDeletion(xml, xsltParameters); } static Templates xsltMarkupAsDeletion; public final static org.docx4j.wml.SdtBlock markupAsDeletion( String sdtXmlString, Map<String, Object> xsltParameters) throws Exception { StreamSource src = new StreamSource(new StringReader(sdtXmlString)); javax.xml.bind.util.JAXBResult result = new javax.xml.bind.util.JAXBResult( org.docx4j.jaxb.Context.jc); if (xsltMarkupAsDeletion == null) { Source xsltSource = new StreamSource(org.docx4j.utils.ResourceUtils .getResource("org/docx4all/util/MarkupAsDeletion.xslt")); xsltMarkupAsDeletion = XmlUtils.getTransformerTemplate(xsltSource); } org.docx4j.XmlUtils.transform(src, xsltMarkupAsDeletion, xsltParameters, result); org.docx4j.wml.SdtBlock newSdt = (org.docx4j.wml.SdtBlock) result.getResult(); return newSdt; } public final static org.docx4j.wml.SdtBlock markupAsInsertion( org.docx4j.wml.SdtBlock sdt, Changeset changeset) throws Exception { Map<String, Object> params = new HashMap<String, Object>(1); params.put("author", changeset.getModifier()); return markupAsInsertion(sdt, params); } public final static org.docx4j.wml.SdtBlock markupAsInsertion( org.docx4j.wml.SdtBlock sdt, Map<String, Object> xsltParameters) throws Exception { String xml = XmlUtils.marshaltoString(sdt, false); return markupAsInsertion(xml, xsltParameters); } static Templates xsltMarkupAsInsertion; public final static org.docx4j.wml.SdtBlock markupAsInsertion( String sdtXmlString, Map<String, Object> xsltParameters) throws Exception { StreamSource src = new StreamSource(new StringReader(sdtXmlString)); javax.xml.bind.util.JAXBResult result = new javax.xml.bind.util.JAXBResult( org.docx4j.jaxb.Context.jc); if (xsltMarkupAsInsertion == null) { Source xsltSource = new StreamSource(org.docx4j.utils.ResourceUtils .getResource("org/docx4all/util/MarkupAsInsertion.xslt")); xsltMarkupAsInsertion = XmlUtils.getTransformerTemplate(xsltSource); } org.docx4j.XmlUtils.transform(src, xsltMarkupAsInsertion, xsltParameters, result); org.docx4j.wml.SdtBlock newSdt = (org.docx4j.wml.SdtBlock) result.getResult(); return newSdt; } private XmlUtil() { ;//uninstantiable } }// XmlUtil class