first commit
This commit is contained in:
commit
4d332ef662
27586 changed files with 3281783 additions and 0 deletions
324
rus/WEB-INF/lib/docx4j-3.2.1_src/org/docx4j/Docx4J.java
Normal file
324
rus/WEB-INF/lib/docx4j-3.2.1_src/org/docx4j/Docx4J.java
Normal file
|
|
@ -0,0 +1,324 @@
|
|||
package org.docx4j;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import net.engio.mbassy.bus.MBassador;
|
||||
import org.docx4j.convert.out.FOSettings;
|
||||
import org.docx4j.convert.out.HTMLSettings;
|
||||
import org.docx4j.convert.out.common.Exporter;
|
||||
import org.docx4j.convert.out.common.preprocess.PartialDeepCopy;
|
||||
import org.docx4j.convert.out.fo.FOExporterVisitor;
|
||||
import org.docx4j.convert.out.fo.FOExporterXslt;
|
||||
import org.docx4j.convert.out.html.HTMLExporterVisitor;
|
||||
import org.docx4j.convert.out.html.HTMLExporterXslt;
|
||||
import org.docx4j.events.Docx4jEvent;
|
||||
import org.docx4j.events.EventFinished;
|
||||
import org.docx4j.events.PackageIdentifier;
|
||||
import org.docx4j.events.StartEvent;
|
||||
import org.docx4j.events.WellKnownJobTypes;
|
||||
import org.docx4j.events.WellKnownProcessSteps;
|
||||
import org.docx4j.model.datastorage.BindingHandler;
|
||||
import org.docx4j.model.datastorage.CustomXmlDataStoragePartSelector;
|
||||
import org.docx4j.model.datastorage.OpenDoPEHandler;
|
||||
import org.docx4j.model.datastorage.RemovalHandler;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.openpackaging.packages.OpcPackage;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.openpackaging.parts.CustomXmlDataStoragePart;
|
||||
import org.docx4j.openpackaging.parts.Part;
|
||||
import org.docx4j.openpackaging.parts.PartName;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.FooterPart;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.HeaderPart;
|
||||
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
|
||||
import org.docx4j.relationships.Relationship;
|
||||
import org.docx4j.utils.TraversalUtilVisitor;
|
||||
import org.docx4j.wml.SdtElement;
|
||||
import org.docx4j.wml.SdtPr;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
public class Docx4J {
|
||||
public static final String MIME_PDF = "application/pdf";
|
||||
|
||||
public static final String MIME_FO = "application/xml-fo";
|
||||
|
||||
public static final int FLAG_NONE = 0;
|
||||
|
||||
public static final int FLAG_EXPORT_PREFER_XSL = 1;
|
||||
|
||||
public static final int FLAG_EXPORT_PREFER_NONXSL = 2;
|
||||
|
||||
public static final int FLAG_SAVE_ZIP_FILE = 1;
|
||||
|
||||
public static final int FLAG_SAVE_FLAT_XML = 2;
|
||||
|
||||
public static final int FLAG_BIND_INSERT_XML = 1;
|
||||
|
||||
public static final int FLAG_BIND_BIND_XML = 2;
|
||||
|
||||
public static final int FLAG_BIND_REMOVE_SDT = 4;
|
||||
|
||||
public static final int FLAG_BIND_REMOVE_XML = 8;
|
||||
|
||||
private static MBassador<Docx4jEvent> bus;
|
||||
|
||||
protected static final String NS_CONDITIONS = "http://opendope.org/conditions";
|
||||
|
||||
protected static final String NS_XPATHS = "http://opendope.org/xpaths";
|
||||
|
||||
protected static final String NS_QUESTIONS = "http://opendope.org/questions";
|
||||
|
||||
protected static final String NS_COMPONENTS = "http://opendope.org/components";
|
||||
|
||||
public static void setEventNotifier(MBassador<Docx4jEvent> eventbus) {
|
||||
bus = eventbus;
|
||||
}
|
||||
|
||||
protected static class FindContentControlsVisitor extends TraversalUtilVisitor<SdtElement> {
|
||||
public static class BreakException extends RuntimeException {}
|
||||
|
||||
protected Set<String> definedStoreItemIds = null;
|
||||
|
||||
protected String storeItemId = null;
|
||||
|
||||
public FindContentControlsVisitor(Set<String> definedStoreItemIds) {
|
||||
this.definedStoreItemIds = definedStoreItemIds;
|
||||
}
|
||||
|
||||
public void apply(SdtElement element) {
|
||||
SdtPr sdtPr = element.getSdtPr();
|
||||
if (sdtPr.getDataBinding() != null && sdtPr.getDataBinding().getStoreItemID() != null) {
|
||||
String tmp = sdtPr.getDataBinding().getStoreItemID().toLowerCase();
|
||||
if (this.definedStoreItemIds.contains(tmp)) {
|
||||
this.storeItemId = tmp;
|
||||
throw new BreakException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getdefinedStoreItemId() {
|
||||
return this.storeItemId;
|
||||
}
|
||||
}
|
||||
|
||||
protected static final Set<String> PART_TO_REMOVE_SCHEMA_TYPES = new TreeSet<String>();
|
||||
|
||||
static {
|
||||
PART_TO_REMOVE_SCHEMA_TYPES.add("http://opendope.org/conditions");
|
||||
PART_TO_REMOVE_SCHEMA_TYPES.add("http://opendope.org/xpaths");
|
||||
PART_TO_REMOVE_SCHEMA_TYPES.add("http://opendope.org/questions");
|
||||
PART_TO_REMOVE_SCHEMA_TYPES.add("http://opendope.org/components");
|
||||
}
|
||||
|
||||
public static WordprocessingMLPackage load(File inFile) throws Docx4JException {
|
||||
return WordprocessingMLPackage.load(inFile);
|
||||
}
|
||||
|
||||
public static WordprocessingMLPackage load(PackageIdentifier pkgIdentifier, File inFile) throws Docx4JException {
|
||||
return (WordprocessingMLPackage)OpcPackage.load(pkgIdentifier, inFile);
|
||||
}
|
||||
|
||||
public static WordprocessingMLPackage load(InputStream inStream) throws Docx4JException {
|
||||
return WordprocessingMLPackage.load(inStream);
|
||||
}
|
||||
|
||||
public static WordprocessingMLPackage load(PackageIdentifier pkgIdentifier, InputStream inStream) throws Docx4JException {
|
||||
return (WordprocessingMLPackage)OpcPackage.load(pkgIdentifier, inStream);
|
||||
}
|
||||
|
||||
public static void save(WordprocessingMLPackage wmlPackage, File outFile, int flags) throws Docx4JException {
|
||||
wmlPackage.save(outFile, flags);
|
||||
}
|
||||
|
||||
public static void save(WordprocessingMLPackage wmlPackage, OutputStream outStream, int flags) throws Docx4JException {
|
||||
wmlPackage.save(outStream, flags);
|
||||
}
|
||||
|
||||
public static void bind(WordprocessingMLPackage wmlPackage, String xmlDocument, int flags) throws Docx4JException {
|
||||
ByteArrayInputStream xmlStream = null;
|
||||
if (flags == 0)
|
||||
flags = 15;
|
||||
if ((flags & 0x1) == 1)
|
||||
try {
|
||||
xmlStream = new ByteArrayInputStream(xmlDocument.getBytes("UTF-8"));
|
||||
} catch (UnsupportedEncodingException e1) {
|
||||
xmlStream = new ByteArrayInputStream(xmlDocument.getBytes());
|
||||
}
|
||||
bind(wmlPackage, xmlStream, flags);
|
||||
}
|
||||
|
||||
public static void bind(WordprocessingMLPackage wmlPackage, InputStream xmlDocument, int flags) throws Docx4JException {
|
||||
StartEvent bindJobStartEvent = new StartEvent(WellKnownJobTypes.BIND, wmlPackage);
|
||||
bindJobStartEvent.publish();
|
||||
if (flags == 0)
|
||||
flags = 15;
|
||||
Document xmlDoc = null;
|
||||
if ((flags & 0x1) == 1)
|
||||
try {
|
||||
xmlDoc = XmlUtils.getNewDocumentBuilder().parse(xmlDocument);
|
||||
} catch (Exception e) {
|
||||
throw new Docx4JException("Problems creating a org.w3c.dom.Document for the passed input stream.", e);
|
||||
}
|
||||
bind(wmlPackage, xmlDoc, flags);
|
||||
new EventFinished(bindJobStartEvent).publish();
|
||||
}
|
||||
|
||||
public static void bind(WordprocessingMLPackage wmlPackage, Document xmlDocument, int flags) throws Docx4JException {
|
||||
OpenDoPEHandler openDoPEHandler = null;
|
||||
CustomXmlDataStoragePart customXmlDataStoragePart = null;
|
||||
RemovalHandler removalHandler = null;
|
||||
AtomicInteger bookmarkId = null;
|
||||
if (flags == 0)
|
||||
flags = 15;
|
||||
customXmlDataStoragePart = CustomXmlDataStoragePartSelector.getCustomXmlDataStoragePart(wmlPackage);
|
||||
if (customXmlDataStoragePart == null)
|
||||
throw new Docx4JException("Couldn't find CustomXmlDataStoragePart! exiting..");
|
||||
if ((flags & 0x1) == 1) {
|
||||
StartEvent startEvent = new StartEvent(WellKnownJobTypes.BIND, wmlPackage, WellKnownProcessSteps.BIND_INSERT_XML);
|
||||
startEvent.publish();
|
||||
insertXMLData(customXmlDataStoragePart, xmlDocument);
|
||||
new EventFinished(startEvent).publish();
|
||||
}
|
||||
if ((flags & 0x2) == 2) {
|
||||
StartEvent startEvent = new StartEvent(WellKnownJobTypes.BIND, wmlPackage, WellKnownProcessSteps.BIND_BIND_XML);
|
||||
startEvent.publish();
|
||||
if (wmlPackage.getMainDocumentPart().getXPathsPart() != null) {
|
||||
openDoPEHandler = new OpenDoPEHandler(wmlPackage);
|
||||
openDoPEHandler.preprocess();
|
||||
bookmarkId = openDoPEHandler.getNextBookmarkId();
|
||||
}
|
||||
BindingHandler bh = new BindingHandler(wmlPackage);
|
||||
bh.setStartingIdForNewBookmarks(bookmarkId);
|
||||
bh.applyBindings();
|
||||
new EventFinished(startEvent).publish();
|
||||
}
|
||||
if ((flags & 0x4) == 4) {
|
||||
StartEvent startEvent = new StartEvent(WellKnownJobTypes.BIND, wmlPackage, WellKnownProcessSteps.BIND_REMOVE_SDT);
|
||||
startEvent.publish();
|
||||
removeSDTs(wmlPackage);
|
||||
new EventFinished(startEvent).publish();
|
||||
}
|
||||
if ((flags & 0x8) == 8) {
|
||||
StartEvent startEvent = new StartEvent(WellKnownJobTypes.BIND, wmlPackage, WellKnownProcessSteps.BIND_REMOVE_XML);
|
||||
startEvent.publish();
|
||||
removeDefinedCustomXmlParts(wmlPackage, customXmlDataStoragePart);
|
||||
new EventFinished(startEvent).publish();
|
||||
}
|
||||
}
|
||||
|
||||
protected static void insertXMLData(CustomXmlDataStoragePart customXmlDataStoragePart, Document xmlDocument) throws Docx4JException {
|
||||
customXmlDataStoragePart.getData().setDocument(xmlDocument);
|
||||
}
|
||||
|
||||
protected static String findXPathStorageItemIdInContentControls(WordprocessingMLPackage wmlPackage) {
|
||||
FindContentControlsVisitor visitor = null;
|
||||
if (wmlPackage.getCustomXmlDataStorageParts() != null && !wmlPackage.getCustomXmlDataStorageParts().isEmpty())
|
||||
try {
|
||||
visitor = new FindContentControlsVisitor(wmlPackage.getCustomXmlDataStorageParts().keySet());
|
||||
TraversalUtil.visit(wmlPackage, false, visitor);
|
||||
} catch (FindContentControlsVisitor.BreakException be) {}
|
||||
return (visitor != null) ? visitor.getdefinedStoreItemId() : null;
|
||||
}
|
||||
|
||||
protected static void removeSDTs(WordprocessingMLPackage wmlPackage) throws Docx4JException {
|
||||
RemovalHandler removalHandler = new RemovalHandler();
|
||||
removalHandler.removeSDTs(wmlPackage.getMainDocumentPart(), RemovalHandler.Quantifier.ALL, (String[])null);
|
||||
for (Part part : wmlPackage.getParts().getParts().values()) {
|
||||
if (part instanceof HeaderPart) {
|
||||
removalHandler.removeSDTs((HeaderPart)part, RemovalHandler.Quantifier.ALL, (String[])null);
|
||||
continue;
|
||||
}
|
||||
if (part instanceof FooterPart)
|
||||
removalHandler.removeSDTs((FooterPart)part, RemovalHandler.Quantifier.ALL, (String[])null);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void removeDefinedCustomXmlParts(WordprocessingMLPackage wmlPackage, CustomXmlDataStoragePart customXmlDataStoragePart) {
|
||||
List<PartName> partsToRemove = new ArrayList<PartName>();
|
||||
RelationshipsPart relationshipsPart = wmlPackage.getMainDocumentPart().getRelationshipsPart();
|
||||
List<Relationship> relationshipsList = (relationshipsPart != null && relationshipsPart.getRelationships() != null) ? relationshipsPart.getRelationships().getRelationship() : null;
|
||||
Part part = null;
|
||||
if (relationshipsList != null)
|
||||
for (Relationship relationship : relationshipsList) {
|
||||
if ("http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml".equals(relationship.getType())) {
|
||||
part = relationshipsPart.getPart(relationship);
|
||||
if (part == customXmlDataStoragePart)
|
||||
partsToRemove.add(part.getPartName());
|
||||
}
|
||||
}
|
||||
if (!partsToRemove.isEmpty())
|
||||
for (int i = 0; i < partsToRemove.size(); i++)
|
||||
relationshipsPart.removePart(partsToRemove.get(i));
|
||||
}
|
||||
|
||||
public static WordprocessingMLPackage clone(WordprocessingMLPackage wmlPackage) throws Docx4JException {
|
||||
return (WordprocessingMLPackage)PartialDeepCopy.process(wmlPackage, null);
|
||||
}
|
||||
|
||||
public static FOSettings createFOSettings() {
|
||||
return new FOSettings();
|
||||
}
|
||||
|
||||
public static void toFO(FOSettings settings, OutputStream outputStream, int flags) throws Docx4JException {
|
||||
Exporter<FOSettings> exporter = getFOExporter(flags);
|
||||
exporter.export(settings, outputStream);
|
||||
}
|
||||
|
||||
public static void toPDF(WordprocessingMLPackage wmlPackage, OutputStream outputStream) throws Docx4JException {
|
||||
StartEvent startEvent = new StartEvent(wmlPackage, WellKnownProcessSteps.PDF);
|
||||
startEvent.publish();
|
||||
FOSettings settings = createFOSettings();
|
||||
settings.setWmlPackage(wmlPackage);
|
||||
settings.setApacheFopMime("application/pdf");
|
||||
toFO(settings, outputStream, 0);
|
||||
new EventFinished(startEvent).publish();
|
||||
}
|
||||
|
||||
protected static Exporter<FOSettings> getFOExporter(int flags) {
|
||||
switch (flags) {
|
||||
case 2:
|
||||
return FOExporterVisitor.getInstance();
|
||||
}
|
||||
return FOExporterXslt.getInstance();
|
||||
}
|
||||
|
||||
public static HTMLSettings createHTMLSettings() {
|
||||
return new HTMLSettings();
|
||||
}
|
||||
|
||||
public static void toHTML(HTMLSettings settings, OutputStream outputStream, int flags) throws Docx4JException {
|
||||
StartEvent startEvent = new StartEvent(settings.getWmlPackage(), WellKnownProcessSteps.HTML_OUT);
|
||||
startEvent.publish();
|
||||
Exporter<HTMLSettings> exporter = getHTMLExporter(flags);
|
||||
exporter.export(settings, outputStream);
|
||||
new EventFinished(startEvent).publish();
|
||||
}
|
||||
|
||||
public static void toHTML(WordprocessingMLPackage wmlPackage, String imageDirPath, String imageTargetUri, OutputStream outputStream) throws Docx4JException {
|
||||
StartEvent startEvent = new StartEvent(wmlPackage, WellKnownProcessSteps.HTML_OUT);
|
||||
startEvent.publish();
|
||||
HTMLSettings settings = createHTMLSettings();
|
||||
settings.setWmlPackage(wmlPackage);
|
||||
if (imageDirPath != null)
|
||||
settings.setImageDirPath(imageDirPath);
|
||||
if (imageTargetUri != null)
|
||||
settings.setImageTargetUri(imageTargetUri);
|
||||
toHTML(settings, outputStream, 0);
|
||||
new EventFinished(startEvent).publish();
|
||||
}
|
||||
|
||||
protected static Exporter<HTMLSettings> getHTMLExporter(int flags) {
|
||||
switch (flags) {
|
||||
case 2:
|
||||
return HTMLExporterVisitor.getInstance();
|
||||
}
|
||||
return HTMLExporterXslt.getInstance();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package org.docx4j;
|
||||
|
||||
import java.util.Properties;
|
||||
import org.docx4j.utils.ResourceUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Docx4jProperties {
|
||||
protected static Logger log = LoggerFactory.getLogger(Docx4jProperties.class);
|
||||
|
||||
private static Properties properties;
|
||||
|
||||
private static void init() {
|
||||
properties = new Properties();
|
||||
try {
|
||||
properties.load(ResourceUtils.getResource("docx4j.properties"));
|
||||
} catch (Exception e) {
|
||||
log.warn("Couldn't find/read docx4j.properties; " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static String getProperty(String key) {
|
||||
if (properties == null)
|
||||
init();
|
||||
return properties.getProperty(key);
|
||||
}
|
||||
|
||||
public static String getProperty(String key, String defaultValue) {
|
||||
if (properties == null)
|
||||
init();
|
||||
return properties.getProperty(key, defaultValue);
|
||||
}
|
||||
|
||||
public static boolean getProperty(String key, boolean defaultValue) {
|
||||
if (properties == null)
|
||||
init();
|
||||
String result = properties.getProperty(key, Boolean.toString(defaultValue));
|
||||
return Boolean.parseBoolean(result);
|
||||
}
|
||||
|
||||
public static Properties getProperties() {
|
||||
if (properties == null)
|
||||
init();
|
||||
return properties;
|
||||
}
|
||||
|
||||
public static void setProperty(String key, Boolean value) {
|
||||
if (properties == null)
|
||||
init();
|
||||
properties.setProperty(key, value.toString());
|
||||
}
|
||||
|
||||
public static void setProperty(String key, String value) {
|
||||
if (properties == null)
|
||||
init();
|
||||
properties.setProperty(key, value);
|
||||
}
|
||||
}
|
||||
65
rus/WEB-INF/lib/docx4j-3.2.1_src/org/docx4j/TextUtils.java
Normal file
65
rus/WEB-INF/lib/docx4j-3.2.1_src/org/docx4j/TextUtils.java
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
package org.docx4j;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.namespace.QName;
|
||||
import org.docx4j.jaxb.Context;
|
||||
import org.docx4j.jaxb.NamespacePrefixMapperUtils;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
|
||||
import org.docx4j.wml.Document;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
public class TextUtils {
|
||||
private static Logger log = LoggerFactory.getLogger(TextUtils.class);
|
||||
|
||||
public static void extractText(Object o, Writer w) throws Exception {
|
||||
extractText(o, w, Context.jc);
|
||||
}
|
||||
|
||||
public static void extractText(Object o, Writer w, JAXBContext jc) throws Exception {
|
||||
Marshaller marshaller = jc.createMarshaller();
|
||||
NamespacePrefixMapperUtils.setProperty(marshaller, NamespacePrefixMapperUtils.getPrefixMapper());
|
||||
marshaller.marshal(o, new TextExtractor(w));
|
||||
}
|
||||
|
||||
public static void extractText(Object o, Writer w, JAXBContext jc, String uri, String local, Class declaredType) throws Exception {
|
||||
Marshaller marshaller = jc.createMarshaller();
|
||||
NamespacePrefixMapperUtils.setProperty(marshaller, NamespacePrefixMapperUtils.getPrefixMapper());
|
||||
marshaller.marshal(new JAXBElement(new QName(uri, local), declaredType, o), new TextExtractor(w));
|
||||
}
|
||||
|
||||
static class TextExtractor extends DefaultHandler {
|
||||
private Writer out;
|
||||
|
||||
public TextExtractor(Writer out) {
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
public void characters(char[] text, int start, int length) throws SAXException {
|
||||
try {
|
||||
this.out.write(text, start, length);
|
||||
} catch (IOException e) {
|
||||
throw new SAXException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String inputfilepath = System.getProperty("user.dir") + "/sample-docs/Table.docx";
|
||||
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(new File(inputfilepath));
|
||||
MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();
|
||||
Document wmlDocumentEl = documentPart.getJaxbElement();
|
||||
Writer out = new OutputStreamWriter(System.out);
|
||||
extractText(wmlDocumentEl, out);
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
380
rus/WEB-INF/lib/docx4j-3.2.1_src/org/docx4j/TraversalUtil.java
Normal file
380
rus/WEB-INF/lib/docx4j-3.2.1_src/org/docx4j/TraversalUtil.java
Normal file
|
|
@ -0,0 +1,380 @@
|
|||
package org.docx4j;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import org.docx4j.dml.CTGvmlGroupShape;
|
||||
import org.docx4j.dml.CTGvmlPicture;
|
||||
import org.docx4j.dml.CTHyperlink;
|
||||
import org.docx4j.dml.CTNonVisualDrawingProps;
|
||||
import org.docx4j.dml.Graphic;
|
||||
import org.docx4j.dml.GraphicData;
|
||||
import org.docx4j.dml.diagram.CTDataModel;
|
||||
import org.docx4j.dml.diagram2008.CTDrawing;
|
||||
import org.docx4j.dml.picture.Pic;
|
||||
import org.docx4j.dml.wordprocessingDrawing.Anchor;
|
||||
import org.docx4j.dml.wordprocessingDrawing.Inline;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.CommentsPart;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.EndnotesPart;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.FooterPart;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.FootnotesPart;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.HeaderPart;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
|
||||
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
|
||||
import org.docx4j.relationships.Relationship;
|
||||
import org.docx4j.utils.CompoundTraversalUtilVisitorCallback;
|
||||
import org.docx4j.utils.SingleTraversalUtilVisitorCallback;
|
||||
import org.docx4j.utils.TraversalUtilVisitor;
|
||||
import org.docx4j.vml.CTShape;
|
||||
import org.docx4j.vml.CTTextbox;
|
||||
import org.docx4j.wml.Body;
|
||||
import org.docx4j.wml.CTObject;
|
||||
import org.docx4j.wml.CTTxbxContent;
|
||||
import org.docx4j.wml.Comments;
|
||||
import org.docx4j.wml.ContentAccessor;
|
||||
import org.docx4j.wml.Document;
|
||||
import org.docx4j.wml.FldChar;
|
||||
import org.docx4j.wml.Pict;
|
||||
import org.docx4j.wml.SdtBlock;
|
||||
import org.docx4j.wml.SdtElement;
|
||||
import org.docx4j.wml.Text;
|
||||
import org.jvnet.jaxb2_commons.ppp.Child;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
public class TraversalUtil {
|
||||
private static Logger log = LoggerFactory.getLogger(TraversalUtil.class);
|
||||
|
||||
Callback cb;
|
||||
|
||||
public static abstract class CallbackImpl implements Callback {
|
||||
public void walkJAXBElements(Object parent) {
|
||||
List<Object> children = getChildren(parent);
|
||||
if (children != null)
|
||||
for (Object o : children) {
|
||||
o = XmlUtils.unwrap(o);
|
||||
if (o instanceof Child)
|
||||
if (parent instanceof SdtBlock) {
|
||||
((Child)o).setParent(((SdtBlock)parent).getSdtContent());
|
||||
} else {
|
||||
((Child)o).setParent(parent);
|
||||
}
|
||||
apply(o);
|
||||
if (shouldTraverse(o))
|
||||
walkJAXBElements(o);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Object> getChildren(Object o) {
|
||||
return TraversalUtil.getChildrenImpl(o);
|
||||
}
|
||||
|
||||
public abstract List<Object> apply(Object param1Object);
|
||||
|
||||
public boolean shouldTraverse(Object o) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public TraversalUtil(Object parent, Callback cb) {
|
||||
this.cb = cb;
|
||||
cb.walkJAXBElements(parent);
|
||||
}
|
||||
|
||||
static void visitChildrenImpl(Object o) {}
|
||||
|
||||
private static List<Object> handleGraphicData(GraphicData graphicData) {
|
||||
List<Object> tmpArtificialList = new ArrayList();
|
||||
if (graphicData.getPic() != null) {
|
||||
CTNonVisualDrawingProps picNonVisual = graphicData.getPic().getNvPicPr().getCNvPr();
|
||||
if (picNonVisual != null)
|
||||
handleCTNonVisualDrawingProps(picNonVisual, tmpArtificialList);
|
||||
}
|
||||
if (graphicData.getPic() != null && graphicData.getPic().getBlipFill() != null && graphicData.getPic().getBlipFill().getBlip() != null) {
|
||||
log.debug("found CTBlip");
|
||||
List<Object> artificialList = new ArrayList();
|
||||
if (!tmpArtificialList.isEmpty())
|
||||
artificialList.addAll(tmpArtificialList);
|
||||
artificialList.add(graphicData.getPic().getBlipFill().getBlip());
|
||||
return artificialList;
|
||||
}
|
||||
return graphicData.getAny();
|
||||
}
|
||||
|
||||
private static void handleCTNonVisualDrawingProps(CTNonVisualDrawingProps drawingProps, List<Object> artificialList) {
|
||||
if (drawingProps != null) {
|
||||
CTHyperlink docPrHyperLink = drawingProps.getHlinkClick();
|
||||
if (docPrHyperLink != null)
|
||||
artificialList.add(docPrHyperLink);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Object> getChildrenImpl(Object o) {
|
||||
if (o == null) {
|
||||
log.warn("null passed to getChildrenImpl");
|
||||
return null;
|
||||
}
|
||||
log.debug("getting children of " + o.getClass().getName());
|
||||
if (o instanceof Text)
|
||||
return null;
|
||||
if (o instanceof List)
|
||||
return (List<Object>)o;
|
||||
if (o instanceof ContentAccessor)
|
||||
return ((ContentAccessor)o).getContent();
|
||||
if (o instanceof SdtElement)
|
||||
return ((SdtElement)o).getSdtContent().getContent();
|
||||
if (o instanceof Anchor) {
|
||||
Anchor anchor = (Anchor)o;
|
||||
List<Object> artificialList = new ArrayList();
|
||||
CTNonVisualDrawingProps drawingProps = anchor.getDocPr();
|
||||
if (drawingProps != null)
|
||||
handleCTNonVisualDrawingProps(drawingProps, artificialList);
|
||||
if (anchor.getGraphic() != null) {
|
||||
log.debug("found a:graphic");
|
||||
Graphic graphic = anchor.getGraphic();
|
||||
if (graphic.getGraphicData() != null)
|
||||
artificialList.addAll(handleGraphicData(graphic.getGraphicData()));
|
||||
}
|
||||
if (!artificialList.isEmpty())
|
||||
return artificialList;
|
||||
} else if (o instanceof Inline) {
|
||||
Inline inline = (Inline)o;
|
||||
List<Object> artificialList = new ArrayList();
|
||||
CTNonVisualDrawingProps drawingProps = inline.getDocPr();
|
||||
if (drawingProps != null)
|
||||
handleCTNonVisualDrawingProps(drawingProps, artificialList);
|
||||
if (inline.getGraphic() != null) {
|
||||
log.debug("found a:graphic");
|
||||
Graphic graphic = inline.getGraphic();
|
||||
if (graphic.getGraphicData() != null)
|
||||
artificialList.addAll(handleGraphicData(graphic.getGraphicData()));
|
||||
return artificialList;
|
||||
}
|
||||
if (!artificialList.isEmpty())
|
||||
return artificialList;
|
||||
} else {
|
||||
if (o instanceof Pict)
|
||||
return ((Pict)o).getAnyAndAny();
|
||||
if (o instanceof Pic) {
|
||||
Pic dmlPic = (Pic)o;
|
||||
if (dmlPic.getBlipFill() != null && dmlPic.getBlipFill().getBlip() != null) {
|
||||
log.debug("found DML Blip");
|
||||
List<Object> artificialList = new ArrayList();
|
||||
artificialList.add(dmlPic.getBlipFill().getBlip());
|
||||
return artificialList;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (o instanceof CTGvmlPicture) {
|
||||
CTGvmlPicture dmlPic = (CTGvmlPicture)o;
|
||||
if (dmlPic.getBlipFill() != null && dmlPic.getBlipFill().getBlip() != null) {
|
||||
log.debug("found DML Blip");
|
||||
List<Object> artificialList = new ArrayList();
|
||||
artificialList.add(dmlPic.getBlipFill().getBlip());
|
||||
return artificialList;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (o instanceof CTShape) {
|
||||
List<Object> artificialList = new ArrayList();
|
||||
for (JAXBElement<?> j : ((CTShape)o).getPathOrFormulasOrHandles())
|
||||
artificialList.add(j);
|
||||
return artificialList;
|
||||
}
|
||||
if (o instanceof CTDataModel) {
|
||||
CTDataModel dataModel = (CTDataModel)o;
|
||||
List<Object> artificialList = new ArrayList();
|
||||
artificialList.addAll(dataModel.getPtLst().getPt());
|
||||
artificialList.addAll(dataModel.getCxnLst().getCxn());
|
||||
return artificialList;
|
||||
}
|
||||
if (o instanceof CTDrawing)
|
||||
return ((CTDrawing)o).getSpTree().getSpOrGrpSp();
|
||||
if (o instanceof CTTextbox) {
|
||||
CTTextbox textBox = (CTTextbox)o;
|
||||
if (textBox.getTxbxContent() == null)
|
||||
return null;
|
||||
return textBox.getTxbxContent().getEGBlockLevelElts();
|
||||
}
|
||||
if (o instanceof CTObject) {
|
||||
CTObject ctObject = (CTObject)o;
|
||||
List<Object> artificialList = new ArrayList();
|
||||
artificialList.addAll(ctObject.getAnyAndAny());
|
||||
if (ctObject.getControl() != null)
|
||||
artificialList.add(ctObject.getControl());
|
||||
return artificialList;
|
||||
}
|
||||
if (o instanceof CTGvmlGroupShape)
|
||||
return ((CTGvmlGroupShape)o).getTxSpOrSpOrCxnSp();
|
||||
if (o instanceof FldChar) {
|
||||
FldChar fldChar = (FldChar)o;
|
||||
List<Object> artificialList = new ArrayList();
|
||||
artificialList.add(fldChar.getFldCharType());
|
||||
if (fldChar.getFfData() != null)
|
||||
artificialList.add(fldChar.getFfData());
|
||||
if (fldChar.getFldData() != null)
|
||||
artificialList.add(fldChar.getFldData());
|
||||
if (fldChar.getNumberingChange() != null)
|
||||
artificialList.add(fldChar.getNumberingChange());
|
||||
return artificialList;
|
||||
}
|
||||
}
|
||||
log.debug(".. looking for method which returns list ");
|
||||
try {
|
||||
Method[] methods = o.getClass().getDeclaredMethods();
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
Method m = methods[i];
|
||||
if (m.getReturnType().getName().equals("java.util.List"))
|
||||
return (List<Object>)m.invoke(o);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
log.debug(".. no list member");
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String inputfilepath = System.getProperty("user.dir") + "/sample-docs/sample-docx.xml";
|
||||
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(new File(inputfilepath));
|
||||
MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();
|
||||
Document wmlDocumentEl = documentPart.getJaxbElement();
|
||||
Body body = wmlDocumentEl.getBody();
|
||||
new TraversalUtil(body, new Callback() {
|
||||
String indent = "";
|
||||
|
||||
public List<Object> apply(Object o) {
|
||||
String text = "";
|
||||
if (o instanceof Text)
|
||||
text = ((Text)o).getValue();
|
||||
System.out.println(this.indent + o.getClass().getName() + " \"" + text + "\"");
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean shouldTraverse(Object o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void walkJAXBElements(Object parent) {
|
||||
this.indent += " ";
|
||||
List<Object> children = getChildren(parent);
|
||||
if (children != null)
|
||||
for (Object o : children) {
|
||||
o = XmlUtils.unwrap(o);
|
||||
apply(o);
|
||||
if (shouldTraverse(o))
|
||||
walkJAXBElements(o);
|
||||
}
|
||||
this.indent = this.indent.substring(0, this.indent.length() - 4);
|
||||
}
|
||||
|
||||
public List<Object> getChildren(Object o) {
|
||||
return TraversalUtil.getChildrenImpl(o);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static interface Callback {
|
||||
void walkJAXBElements(Object param1Object);
|
||||
|
||||
List<Object> getChildren(Object param1Object);
|
||||
|
||||
List<Object> apply(Object param1Object);
|
||||
|
||||
boolean shouldTraverse(Object param1Object);
|
||||
}
|
||||
|
||||
public static void replaceChildren(Object o, List<Object> newChildren) {
|
||||
log.debug("Clearing " + o.getClass().getName());
|
||||
if (o instanceof ContentAccessor) {
|
||||
((ContentAccessor)o).getContent().clear();
|
||||
((ContentAccessor)o).getContent().addAll(newChildren);
|
||||
} else if (o instanceof SdtElement) {
|
||||
((SdtElement)o).getSdtContent().getContent().clear();
|
||||
((SdtElement)o).getSdtContent().getContent().addAll(newChildren);
|
||||
} else if (o instanceof CTTxbxContent) {
|
||||
((CTTxbxContent)o).getEGBlockLevelElts().clear();
|
||||
((CTTxbxContent)o).getEGBlockLevelElts().addAll(newChildren);
|
||||
} else {
|
||||
log.warn("Don't know how to replaceChildren in " + o.getClass().getName());
|
||||
if (o instanceof Node)
|
||||
log.warn(" IGNORED " + ((Node)o).getNodeName());
|
||||
}
|
||||
}
|
||||
|
||||
public static void visit(WordprocessingMLPackage wmlPackage, boolean bodyOnly, TraversalUtilVisitor visitor) {
|
||||
if (visitor != null)
|
||||
visit(wmlPackage, bodyOnly, new SingleTraversalUtilVisitorCallback(visitor));
|
||||
}
|
||||
|
||||
public static void visit(Object parent, TraversalUtilVisitor visitor) {
|
||||
if (visitor != null)
|
||||
visit(parent, new SingleTraversalUtilVisitorCallback(visitor));
|
||||
}
|
||||
|
||||
public static void visit(WordprocessingMLPackage wmlPackage, boolean bodyOnly, List<TraversalUtilVisitor> visitorList) {
|
||||
CompoundTraversalUtilVisitorCallback callback = null;
|
||||
if (visitorList != null && !visitorList.isEmpty())
|
||||
if (visitorList.size() > 1) {
|
||||
visit(wmlPackage, bodyOnly, new CompoundTraversalUtilVisitorCallback(visitorList));
|
||||
} else {
|
||||
visit(wmlPackage, bodyOnly, visitorList.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
public static void visit(Object parent, List<TraversalUtilVisitor> visitorList) {
|
||||
CompoundTraversalUtilVisitorCallback callback = null;
|
||||
if (visitorList != null && !visitorList.isEmpty())
|
||||
if (visitorList.size() > 1) {
|
||||
visit(parent, new CompoundTraversalUtilVisitorCallback(visitorList));
|
||||
} else {
|
||||
visit(parent, visitorList.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
public static void visit(Object parent, Callback callback) {
|
||||
if (parent != null && callback != null)
|
||||
callback.walkJAXBElements(parent);
|
||||
}
|
||||
|
||||
public static void visit(WordprocessingMLPackage wmlPackage, boolean bodyOnly, Callback callback) {
|
||||
MainDocumentPart mainDocument = null;
|
||||
RelationshipsPart relPart = null;
|
||||
List<Relationship> relList = null;
|
||||
List<Object> elementList = null;
|
||||
if (wmlPackage != null && callback != null) {
|
||||
mainDocument = wmlPackage.getMainDocumentPart();
|
||||
callback.walkJAXBElements(mainDocument.getJaxbElement().getBody());
|
||||
if (!bodyOnly) {
|
||||
relPart = mainDocument.getRelationshipsPart();
|
||||
relList = relPart.getRelationships().getRelationship();
|
||||
for (Relationship rs : relList) {
|
||||
elementList = null;
|
||||
if ("http://schemas.openxmlformats.org/officeDocument/2006/relationships/header".equals(rs.getType())) {
|
||||
elementList = ((HeaderPart)relPart.getPart(rs)).getJaxbElement().getContent();
|
||||
} else if ("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer".equals(rs.getType())) {
|
||||
elementList = ((FooterPart)relPart.getPart(rs)).getJaxbElement().getContent();
|
||||
} else if ("http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes".equals(rs.getType())) {
|
||||
elementList = new ArrayList();
|
||||
elementList.addAll(((EndnotesPart)relPart.getPart(rs)).getJaxbElement().getEndnote());
|
||||
} else if ("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes".equals(rs.getType())) {
|
||||
elementList = new ArrayList();
|
||||
elementList.addAll(((FootnotesPart)relPart.getPart(rs)).getJaxbElement().getFootnote());
|
||||
} else if ("http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments".equals(rs.getType())) {
|
||||
elementList = new ArrayList();
|
||||
for (Comments.Comment comment : ((CommentsPart)relPart.getPart(rs)).getJaxbElement().getComment())
|
||||
elementList.addAll(comment.getEGBlockLevelElts());
|
||||
}
|
||||
if (elementList != null && !elementList.isEmpty()) {
|
||||
log.debug("Processing target: " + rs.getTarget() + ", type: " + rs.getType());
|
||||
callback.walkJAXBElements(elementList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
package org.docx4j;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.util.Locale;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class UnitsOfMeasurement {
|
||||
private static final Logger log = LoggerFactory.getLogger(UnitsOfMeasurement.class);
|
||||
|
||||
public static final DecimalFormat format2DP = new DecimalFormat("##.##", new DecimalFormatSymbols(Locale.ENGLISH));
|
||||
|
||||
public static final int DPI = Integer.parseInt(Docx4jProperties.getProperty("docx4j.DPI", "96"));
|
||||
|
||||
public static long twipToEMU(double twips) {
|
||||
return Math.round(635.0D * twips);
|
||||
}
|
||||
|
||||
public static int inchToTwip(float inch) {
|
||||
return Math.round(inch * 1440.0F);
|
||||
}
|
||||
|
||||
public static float twipToInch(int twip) {
|
||||
return (float)twip / 1440.0F;
|
||||
}
|
||||
|
||||
public static float twipToMm(int twip) {
|
||||
return (float)twip / 56.6928F;
|
||||
}
|
||||
|
||||
public static int mmToTwip(float mm) {
|
||||
float inch = mm * 0.0394F;
|
||||
return inchToTwip(inch);
|
||||
}
|
||||
|
||||
public static float twipToPoint(int twip) {
|
||||
return (float)twip / 20.0F;
|
||||
}
|
||||
|
||||
public static int pointToTwip(float point) {
|
||||
return Math.round(20.0F * point);
|
||||
}
|
||||
|
||||
public static int pxToTwip(float px) {
|
||||
float inch = px / (float)DPI;
|
||||
return inchToTwip(inch);
|
||||
}
|
||||
|
||||
public static String twipToBest(int leftL) {
|
||||
float inch4f = 80.0F * twipToInch(leftL);
|
||||
float inch4fabit = inch4f + 0.49F;
|
||||
int inch4 = Math.round(inch4f);
|
||||
int inch4next = Math.round(inch4fabit);
|
||||
float inches = twipToInch(leftL);
|
||||
if (inch4 == inch4next) {
|
||||
log.debug(leftL + " twips -> " + inches + "inches");
|
||||
return format2DP.format((double)inches) + "in";
|
||||
}
|
||||
float mm = inches / 0.0394F;
|
||||
log.debug(leftL + " twips -> " + mm + "mm (" + format2DP.format((double)inches) + "inches)");
|
||||
return Math.round(mm) + "mm";
|
||||
}
|
||||
|
||||
public static String rgbTripleToHex(float red, float green, float blue) {
|
||||
return getHex(red) + getHex(green) + getHex(blue);
|
||||
}
|
||||
|
||||
private static String getHex(float f) {
|
||||
int i = Math.round(f);
|
||||
if (i <= 16)
|
||||
return "0" + Integer.toHexString(i);
|
||||
return Integer.toHexString(i);
|
||||
}
|
||||
|
||||
public static String toHexColor(int color) {
|
||||
String ret = Integer.toHexString(color).toUpperCase();
|
||||
return (ret.length() < 6) ? ("000000".substring(0, 6 - ret.length()) + ret) : ret;
|
||||
}
|
||||
|
||||
public static int combineColors(int fgColor, int bgColor, int pctFg) {
|
||||
int resColor = 0;
|
||||
if (pctFg < 1) {
|
||||
resColor = bgColor;
|
||||
} else if (pctFg == 100) {
|
||||
resColor = fgColor;
|
||||
} else {
|
||||
int pctBg = 100 - pctFg;
|
||||
resColor = ((fgColor >> 16 & 0xFF) * pctFg + (bgColor >> 16 & 0xFF) * pctBg) / 100 << 16 | ((fgColor >> 8 & 0xFF) * pctFg + (bgColor >> 8 & 0xFF) * pctBg) / 100 << 8 | ((fgColor & 0xFF) * pctFg + (bgColor & 0xFF) * pctBg) / 100;
|
||||
}
|
||||
return resColor;
|
||||
}
|
||||
|
||||
private String calcHexColor(int value) {
|
||||
String ret = Integer.toHexString(value).toUpperCase();
|
||||
return (ret.length() < 6) ? ("000000".substring(0, 6 - ret.length()) + ret) : ret;
|
||||
}
|
||||
}
|
||||
624
rus/WEB-INF/lib/docx4j-3.2.1_src/org/docx4j/XmlUtils.java
Normal file
624
rus/WEB-INF/lib/docx4j-3.2.1_src/org/docx4j/XmlUtils.java
Normal file
|
|
@ -0,0 +1,624 @@
|
|||
package org.docx4j;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.xml.bind.Binder;
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.bind.util.JAXBResult;
|
||||
import javax.xml.namespace.NamespaceContext;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.ErrorListener;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.Templates;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.TransformerFactoryConfigurationError;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import org.docx4j.jaxb.Context;
|
||||
import org.docx4j.jaxb.JAXBAssociation;
|
||||
import org.docx4j.jaxb.JaxbValidationEventHandler;
|
||||
import org.docx4j.jaxb.NamespacePrefixMapperUtils;
|
||||
import org.docx4j.jaxb.NamespacePrefixMappings;
|
||||
import org.docx4j.jaxb.XPathBinderAssociationIsPartialException;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.utils.XPathFactoryUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
public class XmlUtils {
|
||||
private static Logger log = LoggerFactory.getLogger(XmlUtils.class);
|
||||
|
||||
public static String TRANSFORMER_FACTORY_PROCESSOR_XALAN = "org.apache.xalan.processor.TransformerFactoryImpl";
|
||||
|
||||
private static TransformerFactory transformerFactory;
|
||||
|
||||
public static TransformerFactory getTransformerFactory() {
|
||||
return transformerFactory;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static DocumentBuilderFactory getDocumentBuilderFactory() {
|
||||
return documentBuilderFactory;
|
||||
}
|
||||
|
||||
public static DocumentBuilder getNewDocumentBuilder() {
|
||||
synchronized (documentBuilderFactory) {
|
||||
return documentBuilderFactory.newDocumentBuilder();
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
instantiateTransformerFactory();
|
||||
log.debug(System.getProperty("java.vendor"));
|
||||
log.debug(System.getProperty("java.version"));
|
||||
String sp = Docx4jProperties.getProperty("javax.xml.parsers.SAXParserFactory");
|
||||
if (sp != null) {
|
||||
System.setProperty("javax.xml.parsers.SAXParserFactory", sp);
|
||||
log.info("Using " + sp + " (from docx4j.properties)");
|
||||
} else if (Docx4jProperties.getProperty("docx4j.javax.xml.parsers.SAXParserFactory.donotset", false)) {
|
||||
log.info("Not setting docx4j.javax.xml.parsers.SAXParserFactory");
|
||||
} else if ((System.getProperty("java.version").startsWith("1.6") && System.getProperty("java.vendor").startsWith("Sun")) || (System.getProperty("java.version").startsWith("1.7") && System.getProperty("java.vendor").startsWith("Oracle")) || (System.getProperty("java.version").startsWith("1.8") && System.getProperty("java.vendor").startsWith("Oracle")) || (System.getProperty("java.version").startsWith("1.7") && System.getProperty("java.vendor").startsWith("Jeroen"))) {
|
||||
System.setProperty("javax.xml.parsers.SAXParserFactory", "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl");
|
||||
log.info("Using com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl");
|
||||
} else {
|
||||
log.warn("default SAXParserFactory property : " + System.getProperty("javax.xml.parsers.SAXParserFactory") + "\n Please consider using Xerces.");
|
||||
}
|
||||
String dbf = Docx4jProperties.getProperty("javax.xml.parsers.DocumentBuilderFactory");
|
||||
if (dbf != null) {
|
||||
System.setProperty("javax.xml.parsers.DocumentBuilderFactory", dbf);
|
||||
log.info("Using " + dbf + " (from docx4j.properties)");
|
||||
} else if (Docx4jProperties.getProperty("docx4j.javax.xml.parsers.DocumentBuilderFactory.donotset", false)) {
|
||||
log.info("Not setting docx4j.javax.xml.parsers.DocumentBuilderFactory");
|
||||
} else if ((System.getProperty("java.version").startsWith("1.6") && System.getProperty("java.vendor").startsWith("Sun")) || (System.getProperty("java.version").startsWith("1.7") && System.getProperty("java.vendor").startsWith("Oracle")) || (System.getProperty("java.version").startsWith("1.8") && System.getProperty("java.vendor").startsWith("Oracle")) || (System.getProperty("java.version").startsWith("1.7") && System.getProperty("java.vendor").startsWith("Jeroen"))) {
|
||||
System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
|
||||
log.info("Using com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
|
||||
} else {
|
||||
log.warn("default DocumentBuilderFactory property: " + System.getProperty("javax.xml.parsers.DocumentBuilderFactory") + "\n Please consider using Xerces.");
|
||||
}
|
||||
}
|
||||
|
||||
private static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
|
||||
|
||||
static {
|
||||
documentBuilderFactory.setNamespaceAware(true);
|
||||
try {
|
||||
documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
} catch (ParserConfigurationException e) {
|
||||
log.error(e.getMessage(), (Throwable)e);
|
||||
}
|
||||
documentBuilderFactory.setXIncludeAware(false);
|
||||
documentBuilderFactory.setExpandEntityReferences(false);
|
||||
try {
|
||||
documentBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
||||
} catch (ParserConfigurationException e) {
|
||||
log.error(e.getMessage(), (Throwable)e);
|
||||
}
|
||||
try {
|
||||
documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||
} catch (ParserConfigurationException e) {
|
||||
log.error(e.getMessage(), (Throwable)e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void instantiateTransformerFactory() {
|
||||
String originalSystemProperty = System.getProperty("javax.xml.transform.TransformerFactory");
|
||||
try {
|
||||
System.setProperty("javax.xml.transform.TransformerFactory", TRANSFORMER_FACTORY_PROCESSOR_XALAN);
|
||||
transformerFactory = TransformerFactory.newInstance();
|
||||
if (originalSystemProperty == null) {
|
||||
System.clearProperty("javax.xml.transform.TransformerFactory");
|
||||
} else {
|
||||
System.setProperty("javax.xml.transform.TransformerFactory", originalSystemProperty);
|
||||
}
|
||||
} catch (TransformerFactoryConfigurationError e) {
|
||||
log.error("Warning: Xalan jar missing from classpath; xslt not supported", (Throwable)e);
|
||||
if (originalSystemProperty == null) {
|
||||
System.clearProperty("javax.xml.transform.TransformerFactory");
|
||||
} else {
|
||||
System.setProperty("javax.xml.transform.TransformerFactory", originalSystemProperty);
|
||||
}
|
||||
transformerFactory = TransformerFactory.newInstance();
|
||||
}
|
||||
LoggingErrorListener errorListener = new LoggingErrorListener(false);
|
||||
transformerFactory.setErrorListener(errorListener);
|
||||
}
|
||||
|
||||
public static Object unwrap(Object o) {
|
||||
if (o == null)
|
||||
return null;
|
||||
if (o instanceof JAXBElement) {
|
||||
log.debug("Unwrapped " + ((JAXBElement)o).getDeclaredType().getName());
|
||||
log.debug("name: " + ((JAXBElement)o).getName());
|
||||
return ((JAXBElement)o).getValue();
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
public static String JAXBElementDebug(JAXBElement o) {
|
||||
String prefix = null;
|
||||
if (o.getName().getNamespaceURI() != null)
|
||||
try {
|
||||
prefix = NamespacePrefixMapperUtils.getPreferredPrefix(o.getName().getNamespaceURI(), null, false);
|
||||
} catch (JAXBException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (prefix != null)
|
||||
return prefix + ':' + o.getName().getLocalPart() + " is a javax.xml.bind.JAXBElement; it has declared type " + o.getDeclaredType().getName();
|
||||
return o.getName() + " is a javax.xml.bind.JAXBElement; it has declared type " + o.getDeclaredType().getName();
|
||||
}
|
||||
|
||||
public static JAXBElement<?> getListItemByQName(List<JAXBElement<?>> list, QName name) {
|
||||
for (JAXBElement<?> el : list) {
|
||||
if (el.getName().equals(name))
|
||||
return el;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object unmarshal(InputStream is) throws JAXBException {
|
||||
return unmarshal(is, Context.jc);
|
||||
}
|
||||
|
||||
public static Object unmarshal(InputStream is, JAXBContext jc) throws JAXBException {
|
||||
Object o = null;
|
||||
Unmarshaller u = jc.createUnmarshaller();
|
||||
u.setEventHandler(new JaxbValidationEventHandler());
|
||||
o = u.unmarshal(is);
|
||||
return o;
|
||||
}
|
||||
|
||||
public static Object unmarshalString(String str) throws JAXBException {
|
||||
return unmarshalString(str, Context.jc);
|
||||
}
|
||||
|
||||
public static Object unmarshalString(String str, JAXBContext jc, Class declaredType) throws JAXBException {
|
||||
Unmarshaller u = jc.createUnmarshaller();
|
||||
u.setEventHandler(new JaxbValidationEventHandler());
|
||||
Object o = u.unmarshal(new StreamSource(new StringReader(str)), declaredType);
|
||||
if (o instanceof JAXBElement)
|
||||
return ((JAXBElement)o).getValue();
|
||||
return o;
|
||||
}
|
||||
|
||||
public static Object unmarshalString(String str, JAXBContext jc) throws JAXBException {
|
||||
log.debug("Unmarshalling '" + str + "'");
|
||||
Unmarshaller u = jc.createUnmarshaller();
|
||||
u.setEventHandler(new JaxbValidationEventHandler());
|
||||
return u.unmarshal(new StreamSource(new StringReader(str)));
|
||||
}
|
||||
|
||||
public static Object unmarshal(Node n) throws JAXBException {
|
||||
Unmarshaller u = Context.jc.createUnmarshaller();
|
||||
u.setEventHandler(new JaxbValidationEventHandler());
|
||||
return u.unmarshal(n);
|
||||
}
|
||||
|
||||
public static Object unmarshal(Node n, JAXBContext jc, Class declaredType) throws JAXBException {
|
||||
Unmarshaller u = jc.createUnmarshaller();
|
||||
u.setEventHandler(new JaxbValidationEventHandler());
|
||||
Object o = u.unmarshal(n, declaredType);
|
||||
if (o instanceof JAXBElement)
|
||||
return ((JAXBElement)o).getValue();
|
||||
return o;
|
||||
}
|
||||
|
||||
public static Object unmarshallFromTemplate(String wmlTemplateString, HashMap<String, String> mappings) throws JAXBException {
|
||||
return unmarshallFromTemplate(wmlTemplateString, mappings, Context.jc);
|
||||
}
|
||||
|
||||
public static Object unmarshallFromTemplate(String wmlTemplateString, HashMap<String, String> mappings, JAXBContext jc) throws JAXBException {
|
||||
String wmlString = replace(wmlTemplateString, 0, new StringBuilder(), mappings).toString();
|
||||
log.debug("Results of substitution: " + wmlString);
|
||||
return unmarshalString(wmlString, jc);
|
||||
}
|
||||
|
||||
public static Object unmarshallFromTemplate(String wmlTemplateString, HashMap<String, String> mappings, JAXBContext jc, Class<?> declaredType) throws JAXBException {
|
||||
String wmlString = replace(wmlTemplateString, 0, new StringBuilder(), mappings).toString();
|
||||
return unmarshalString(wmlString, jc, declaredType);
|
||||
}
|
||||
|
||||
private static StringBuilder replace(String wmlTemplateString, int offset, StringBuilder strB, HashMap<String, String> mappings) {
|
||||
int startKey = wmlTemplateString.indexOf("${", offset);
|
||||
if (startKey == -1)
|
||||
return strB.append(wmlTemplateString.substring(offset));
|
||||
strB.append(wmlTemplateString.substring(offset, startKey));
|
||||
int keyEnd = wmlTemplateString.indexOf('}', startKey);
|
||||
String key = wmlTemplateString.substring(startKey + 2, keyEnd);
|
||||
String val = mappings.get(key);
|
||||
if (val == null) {
|
||||
log.warn("Invalid key '" + key + "' or key not mapped to a value");
|
||||
strB.append(key);
|
||||
} else {
|
||||
strB.append(val);
|
||||
}
|
||||
return replace(wmlTemplateString, keyEnd + 1, strB, mappings);
|
||||
}
|
||||
|
||||
public static String marshaltoString(Object o) {
|
||||
JAXBContext jc = Context.jc;
|
||||
return marshaltoString(o, true, true, jc);
|
||||
}
|
||||
|
||||
public static String marshaltoString(Object o, JAXBContext jc) {
|
||||
return marshaltoString(o, true, true, jc);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static String marshaltoString(Object o, boolean suppressDeclaration) {
|
||||
JAXBContext jc = Context.jc;
|
||||
return marshaltoString(o, suppressDeclaration, false, jc);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static String marshaltoString(Object o, boolean suppressDeclaration, JAXBContext jc) {
|
||||
return marshaltoString(o, suppressDeclaration, false, jc);
|
||||
}
|
||||
|
||||
public static String marshaltoString(Object o, boolean suppressDeclaration, boolean prettyprint) {
|
||||
JAXBContext jc = Context.jc;
|
||||
return marshaltoString(o, suppressDeclaration, prettyprint, jc);
|
||||
}
|
||||
|
||||
public static String marshaltoString(Object o, boolean suppressDeclaration, boolean prettyprint, JAXBContext jc) {
|
||||
if (o == null)
|
||||
return null;
|
||||
try {
|
||||
Marshaller m = jc.createMarshaller();
|
||||
NamespacePrefixMapperUtils.setProperty(m, NamespacePrefixMapperUtils.getPrefixMapper());
|
||||
if (prettyprint)
|
||||
m.setProperty("jaxb.formatted.output", Boolean.valueOf(true));
|
||||
if (suppressDeclaration)
|
||||
m.setProperty("jaxb.fragment", Boolean.valueOf(true));
|
||||
StringWriter sWriter = new StringWriter();
|
||||
m.marshal(o, sWriter);
|
||||
return sWriter.toString();
|
||||
} catch (JAXBException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String marshaltoString(Object o, boolean suppressDeclaration, boolean prettyprint, JAXBContext jc, String uri, String local, Class declaredType) {
|
||||
try {
|
||||
Marshaller m = jc.createMarshaller();
|
||||
NamespacePrefixMapperUtils.setProperty(m, NamespacePrefixMapperUtils.getPrefixMapper());
|
||||
if (prettyprint)
|
||||
m.setProperty("jaxb.formatted.output", Boolean.valueOf(true));
|
||||
if (suppressDeclaration)
|
||||
m.setProperty("jaxb.fragment", Boolean.valueOf(true));
|
||||
StringWriter sWriter = new StringWriter();
|
||||
m.marshal(new JAXBElement(new QName(uri, local), declaredType, o), sWriter);
|
||||
return sWriter.toString();
|
||||
} catch (JAXBException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static InputStream marshaltoInputStream(Object o, boolean suppressDeclaration, JAXBContext jc) {
|
||||
try {
|
||||
Marshaller m = jc.createMarshaller();
|
||||
NamespacePrefixMapperUtils.setProperty(m, NamespacePrefixMapperUtils.getPrefixMapper());
|
||||
if (suppressDeclaration)
|
||||
m.setProperty("jaxb.fragment", Boolean.valueOf(true));
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
m.marshal(o, os);
|
||||
return new ByteArrayInputStream(os.toByteArray());
|
||||
} catch (JAXBException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Document marshaltoW3CDomDocument(Object o) {
|
||||
return marshaltoW3CDomDocument(o, Context.jc);
|
||||
}
|
||||
|
||||
public static Document marshaltoW3CDomDocument(Object o, JAXBContext jc) {
|
||||
try {
|
||||
Marshaller marshaller = jc.createMarshaller();
|
||||
Document doc = getNewDocumentBuilder().newDocument();
|
||||
NamespacePrefixMapperUtils.setProperty(marshaller, NamespacePrefixMapperUtils.getPrefixMapper());
|
||||
marshaller.marshal(o, doc);
|
||||
return doc;
|
||||
} catch (JAXBException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Document marshaltoW3CDomDocument(Object o, JAXBContext jc, String uri, String local, Class declaredType) {
|
||||
try {
|
||||
Marshaller marshaller = jc.createMarshaller();
|
||||
Document doc = getNewDocumentBuilder().newDocument();
|
||||
NamespacePrefixMapperUtils.setProperty(marshaller, NamespacePrefixMapperUtils.getPrefixMapper());
|
||||
marshaller.marshal(new JAXBElement(new QName(uri, local), declaredType, o), doc);
|
||||
return doc;
|
||||
} catch (JAXBException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T deepCopy(T value) {
|
||||
return XmlUtils.<T>deepCopy(value, Context.jc);
|
||||
}
|
||||
|
||||
public static <T> T deepCopy(T value, JAXBContext jc) {
|
||||
if (value == null)
|
||||
throw new IllegalArgumentException("Can't clone a null argument");
|
||||
try {
|
||||
Class<?> valueClass;
|
||||
T res;
|
||||
if (value instanceof JAXBElement) {
|
||||
log.debug("deep copy of JAXBElement..");
|
||||
elem = (JAXBElement)value;
|
||||
valueClass = elem.getDeclaredType();
|
||||
} else {
|
||||
log.debug("deep copy of " + value.getClass().getName());
|
||||
Class<T> classT = (Class<T>)value.getClass();
|
||||
elem = new JAXBElement(new QName("temp"), classT, value);
|
||||
valueClass = classT;
|
||||
}
|
||||
Marshaller mar = jc.createMarshaller();
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream(256);
|
||||
mar.marshal(elem, bout);
|
||||
Unmarshaller unmar = jc.createUnmarshaller();
|
||||
if (log.isDebugEnabled())
|
||||
unmar.setEventHandler(new JaxbValidationEventHandler());
|
||||
JAXBElement<?> elem = unmar.unmarshal(new StreamSource(new ByteArrayInputStream(bout.toByteArray())), valueClass);
|
||||
if (value instanceof JAXBElement) {
|
||||
JAXBElement<?> jAXBElement2 = elem;
|
||||
JAXBElement<?> jAXBElement1 = jAXBElement2;
|
||||
} else {
|
||||
T resT = (T)elem.getValue();
|
||||
res = resT;
|
||||
}
|
||||
return res;
|
||||
} catch (JAXBException ex) {
|
||||
throw new IllegalArgumentException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static String w3CDomNodeToString(Node n) {
|
||||
StringWriter sw = new StringWriter();
|
||||
try {
|
||||
Transformer serializer = transformerFactory.newTransformer();
|
||||
serializer.setOutputProperty("omit-xml-declaration", "yes");
|
||||
serializer.setOutputProperty("method", "xml");
|
||||
serializer.transform(new DOMSource(n), new StreamResult(sw));
|
||||
return sw.toString();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Document neww3cDomDocument() {
|
||||
return getNewDocumentBuilder().newDocument();
|
||||
}
|
||||
|
||||
public static void appendXmlFragment(Document document, Node parent, String fragment) throws IOException, SAXException, ParserConfigurationException {
|
||||
Node fragmentNode = getNewDocumentBuilder().parse(new InputSource(new StringReader(fragment))).getDocumentElement();
|
||||
fragmentNode = document.importNode(fragmentNode, true);
|
||||
parent.appendChild(fragmentNode);
|
||||
}
|
||||
|
||||
public static JAXBResult prepareJAXBResult(JAXBContext context) throws Docx4JException {
|
||||
JAXBResult result;
|
||||
try {
|
||||
Unmarshaller unmarshaller = context.createUnmarshaller();
|
||||
unmarshaller.setEventHandler(new JaxbValidationEventHandler());
|
||||
result = new JAXBResult(unmarshaller);
|
||||
} catch (JAXBException e) {
|
||||
throw new Docx4JException("Error preparing empty JAXB result", e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void transform(Document doc, Templates template, Map<String, Object> transformParameters, Result result) throws Docx4JException {
|
||||
if (doc == null) {
|
||||
Throwable t = new Throwable();
|
||||
throw new Docx4JException("Null DOM Doc", t);
|
||||
}
|
||||
DOMSource domSource = new DOMSource(doc);
|
||||
transform(domSource, template, transformParameters, result);
|
||||
}
|
||||
|
||||
public static Templates getTransformerTemplate(Source xsltSource) throws TransformerConfigurationException {
|
||||
return transformerFactory.newTemplates(xsltSource);
|
||||
}
|
||||
|
||||
public static void transform(Source source, Templates template, Map<String, Object> transformParameters, Result result) throws Docx4JException {
|
||||
Transformer xformer;
|
||||
if (source == null) {
|
||||
Throwable t = new Throwable();
|
||||
throw new Docx4JException("Null Source doc", t);
|
||||
}
|
||||
try {
|
||||
xformer = template.newTransformer();
|
||||
} catch (TransformerConfigurationException e) {
|
||||
throw new Docx4JException("The Transformer is ill-configured", e);
|
||||
}
|
||||
if (!xformer.getClass().getName().equals("org.apache.xalan.transformer.TransformerImpl"))
|
||||
log.error("Detected " + xformer.getClass().getName() + ", but require org.apache.xalan.transformer.TransformerImpl. " + "Ensure Xalan 2.7.0 is on your classpath!");
|
||||
LoggingErrorListener errorListener = new LoggingErrorListener(false);
|
||||
xformer.setErrorListener(errorListener);
|
||||
if (transformParameters != null) {
|
||||
Iterator<Map.Entry> parameterIterator = transformParameters.entrySet().iterator();
|
||||
while (parameterIterator.hasNext()) {
|
||||
Map.Entry pairs = parameterIterator.next();
|
||||
if (pairs.getKey() == null) {
|
||||
log.info("Skipped null key");
|
||||
continue;
|
||||
}
|
||||
if (pairs.getKey().equals("customXsltTemplates"))
|
||||
continue;
|
||||
if (pairs.getValue() == null) {
|
||||
log.warn("parameter '" + pairs.getKey() + "' was null.");
|
||||
continue;
|
||||
}
|
||||
xformer.setParameter((String)pairs.getKey(), pairs.getValue());
|
||||
}
|
||||
}
|
||||
try {
|
||||
xformer.transform(source, result);
|
||||
} catch (TransformerException e) {
|
||||
throw new Docx4JException("Cannot perform the transformation", e);
|
||||
} finally {}
|
||||
}
|
||||
|
||||
public static List<Object> getJAXBNodesViaXPath(Binder<Node> binder, Object jaxbElement, String xpathExpr, boolean refreshXmlFirst) throws JAXBException, XPathBinderAssociationIsPartialException {
|
||||
List<JAXBAssociation> associations = getJAXBAssociationsForXPath(binder, jaxbElement, xpathExpr, refreshXmlFirst);
|
||||
List<Object> resultList = new ArrayList();
|
||||
for (JAXBAssociation association : associations) {
|
||||
if (association.getJaxbObject() == null)
|
||||
throw new XPathBinderAssociationIsPartialException("no object association for xpath result: " + association.getDomNode().getNodeName());
|
||||
resultList.add(association.getJaxbObject());
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
public static List<JAXBAssociation> getJAXBAssociationsForXPath(Binder<Node> binder, Object jaxbElement, String xpathExpr, boolean refreshXmlFirst) throws JAXBException, XPathBinderAssociationIsPartialException {
|
||||
if (refreshXmlFirst)
|
||||
Node node1 = (Node)binder.updateXML(jaxbElement);
|
||||
Node node = (Node)binder.getXMLNode(jaxbElement);
|
||||
List<JAXBAssociation> resultList = new ArrayList<JAXBAssociation>();
|
||||
for (Node n : xpath(node, xpathExpr))
|
||||
resultList.add(new JAXBAssociation(n, binder.getJAXBNode(n)));
|
||||
return resultList;
|
||||
}
|
||||
|
||||
public static List<Node> xpath(Node node, String xpathExpression) {
|
||||
NamespaceContext nsContext = new NamespacePrefixMappings();
|
||||
return xpath(node, xpathExpression, nsContext);
|
||||
}
|
||||
|
||||
public static List<Node> xpath(Node node, String xpathExpression, NamespaceContext nsContext) {
|
||||
log.debug(w3CDomNodeToString(node));
|
||||
XPath xpath = XPathFactoryUtil.newXPath();
|
||||
try {
|
||||
List<Node> result = new ArrayList<Node>();
|
||||
xpath.setNamespaceContext(nsContext);
|
||||
NodeList nl = (NodeList)xpath.evaluate(xpathExpression, node, XPathConstants.NODESET);
|
||||
log.info("evaluate returned " + nl.getLength());
|
||||
for (int i = 0; i < nl.getLength(); i++)
|
||||
result.add(nl.item(i));
|
||||
return result;
|
||||
} catch (XPathExpressionException e) {
|
||||
log.error("Problem with '" + xpathExpression + "'", (Throwable)e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
static class LoggingErrorListener implements ErrorListener {
|
||||
boolean strict;
|
||||
|
||||
public LoggingErrorListener(boolean strict) {}
|
||||
|
||||
public void warning(TransformerException exception) {
|
||||
XmlUtils.log.warn(exception.getMessage(), (Throwable)exception);
|
||||
}
|
||||
|
||||
public void error(TransformerException exception) throws TransformerException {
|
||||
XmlUtils.log.error(exception.getMessage(), (Throwable)exception);
|
||||
if (this.strict)
|
||||
throw exception;
|
||||
}
|
||||
|
||||
public void fatalError(TransformerException exception) throws TransformerException {
|
||||
XmlUtils.log.error(exception.getMessage(), (Throwable)exception);
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
public static void treeCopy(NodeList sourceNodes, Node destParent) {
|
||||
for (int i = 0; i < sourceNodes.getLength(); i++)
|
||||
treeCopy(sourceNodes.item(i), destParent);
|
||||
}
|
||||
|
||||
public static void treeCopy(Node sourceNode, Node destParent) {
|
||||
NodeList nodes;
|
||||
Node newChild;
|
||||
NamedNodeMap atts;
|
||||
int i;
|
||||
NodeList children;
|
||||
log.debug("node type" + sourceNode.getNodeType());
|
||||
switch (sourceNode.getNodeType()) {
|
||||
case 9:
|
||||
case 11:
|
||||
nodes = sourceNode.getChildNodes();
|
||||
if (nodes != null)
|
||||
for (int j = 0; j < nodes.getLength(); j++) {
|
||||
log.debug("child " + j + "of DOCUMENT_NODE");
|
||||
treeCopy(nodes.item(j), destParent);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
log.debug("copying: " + sourceNode.getNodeName());
|
||||
if (destParent instanceof Document) {
|
||||
newChild = ((Document)destParent).createElementNS(sourceNode.getNamespaceURI(), sourceNode.getLocalName());
|
||||
} else if (sourceNode.getNamespaceURI() != null) {
|
||||
newChild = destParent.getOwnerDocument().createElementNS(sourceNode.getNamespaceURI(), sourceNode.getLocalName());
|
||||
} else {
|
||||
newChild = destParent.getOwnerDocument().createElement(sourceNode.getNodeName());
|
||||
}
|
||||
destParent.appendChild(newChild);
|
||||
atts = sourceNode.getAttributes();
|
||||
for (i = 0; i < atts.getLength(); i++) {
|
||||
Attr attr = (Attr)atts.item(i);
|
||||
if (!attr.getNodeName().startsWith("xmlns:"))
|
||||
if (attr.getNamespaceURI() == null) {
|
||||
((Element)newChild).setAttribute(attr.getName(), attr.getValue());
|
||||
} else if (!attr.getNamespaceURI().equals("http://www.w3.org/2000/xmlns/")) {
|
||||
if (attr.getNodeName() != null) {
|
||||
((Element)newChild).setAttributeNS(attr.getNamespaceURI(), attr.getNodeName(), attr.getValue());
|
||||
} else {
|
||||
((Element)newChild).setAttributeNS(attr.getNamespaceURI(), attr.getLocalName(), attr.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
children = sourceNode.getChildNodes();
|
||||
if (children != null)
|
||||
for (int j = 0; j < children.getLength(); j++)
|
||||
treeCopy(children.item(j), newChild);
|
||||
break;
|
||||
case 3:
|
||||
if (destParent.getOwnerDocument() == null && destParent.getNodeName().equals("#document")) {
|
||||
Node textNode = ((Document)destParent).createTextNode(sourceNode.getNodeValue());
|
||||
destParent.appendChild(textNode);
|
||||
} else {
|
||||
Node textNode = destParent.getOwnerDocument().createTextNode(sourceNode.getNodeValue());
|
||||
Node appended = destParent.appendChild(textNode);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package org.docx4j.bibliography;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElementRef;
|
||||
import javax.xml.bind.annotation.XmlElementRefs;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "CT_AuthorType", propOrder = {"artistOrAuthorOrBookAuthor"})
|
||||
public class CTAuthorType {
|
||||
@XmlElementRefs({@XmlElementRef(name = "Counsel", namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", type = JAXBElement.class), @XmlElementRef(name = "Director", namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", type = JAXBElement.class), @XmlElementRef(name = "Composer", namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", type = JAXBElement.class), @XmlElementRef(name = "Performer", namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", type = JAXBElement.class), @XmlElementRef(name = "Conductor", namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", type = JAXBElement.class), @XmlElementRef(name = "BookAuthor", namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", type = JAXBElement.class), @XmlElementRef(name = "Interviewer", namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", type = JAXBElement.class), @XmlElementRef(name = "Editor", namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", type = JAXBElement.class), @XmlElementRef(name = "ProducerName", namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", type = JAXBElement.class), @XmlElementRef(name = "Translator", namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", type = JAXBElement.class), @XmlElementRef(name = "Author", namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", type = JAXBElement.class), @XmlElementRef(name = "Artist", namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", type = JAXBElement.class), @XmlElementRef(name = "Interviewee", namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", type = JAXBElement.class), @XmlElementRef(name = "Compiler", namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", type = JAXBElement.class), @XmlElementRef(name = "Writer", namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", type = JAXBElement.class), @XmlElementRef(name = "Inventor", namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", type = JAXBElement.class)})
|
||||
protected List<JAXBElement<?>> artistOrAuthorOrBookAuthor;
|
||||
|
||||
public List<JAXBElement<?>> getArtistOrAuthorOrBookAuthor() {
|
||||
if (this.artistOrAuthorOrBookAuthor == null)
|
||||
this.artistOrAuthorOrBookAuthor = new ArrayList<JAXBElement<?>>();
|
||||
return this.artistOrAuthorOrBookAuthor;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package org.docx4j.bibliography;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "CT_NameListType", propOrder = {"person"})
|
||||
public class CTNameListType {
|
||||
@XmlElement(name = "Person", required = true)
|
||||
protected List<CTPersonType> person;
|
||||
|
||||
public List<CTPersonType> getPerson() {
|
||||
if (this.person == null)
|
||||
this.person = new ArrayList<CTPersonType>();
|
||||
return this.person;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package org.docx4j.bibliography;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "CT_NameOrCorporateType", propOrder = {"nameList", "corporate"})
|
||||
public class CTNameOrCorporateType {
|
||||
@XmlElement(name = "NameList")
|
||||
protected CTNameListType nameList;
|
||||
|
||||
@XmlElement(name = "Corporate")
|
||||
protected String corporate;
|
||||
|
||||
public CTNameListType getNameList() {
|
||||
return this.nameList;
|
||||
}
|
||||
|
||||
public void setNameList(CTNameListType value) {
|
||||
this.nameList = value;
|
||||
}
|
||||
|
||||
public String getCorporate() {
|
||||
return this.corporate;
|
||||
}
|
||||
|
||||
public void setCorporate(String value) {
|
||||
this.corporate = value;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package org.docx4j.bibliography;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "CT_NameType", propOrder = {"nameList"})
|
||||
public class CTNameType {
|
||||
@XmlElement(name = "NameList", required = true)
|
||||
protected CTNameListType nameList;
|
||||
|
||||
public CTNameListType getNameList() {
|
||||
return this.nameList;
|
||||
}
|
||||
|
||||
public void setNameList(CTNameListType value) {
|
||||
this.nameList = value;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package org.docx4j.bibliography;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "CT_PersonType", propOrder = {"last", "first", "middle"})
|
||||
public class CTPersonType {
|
||||
@XmlElement(name = "Last")
|
||||
protected List<String> last;
|
||||
|
||||
@XmlElement(name = "First")
|
||||
protected List<String> first;
|
||||
|
||||
@XmlElement(name = "Middle")
|
||||
protected List<String> middle;
|
||||
|
||||
public List<String> getLast() {
|
||||
if (this.last == null)
|
||||
this.last = new ArrayList<String>();
|
||||
return this.last;
|
||||
}
|
||||
|
||||
public List<String> getFirst() {
|
||||
if (this.first == null)
|
||||
this.first = new ArrayList<String>();
|
||||
return this.first;
|
||||
}
|
||||
|
||||
public List<String> getMiddle() {
|
||||
if (this.middle == null)
|
||||
this.middle = new ArrayList<String>();
|
||||
return this.middle;
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,55 @@
|
|||
package org.docx4j.bibliography;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "CT_Sources", propOrder = {"source"})
|
||||
public class CTSources {
|
||||
@XmlElement(name = "Source")
|
||||
protected List<CTSourceType> source;
|
||||
|
||||
@XmlAttribute(name = "SelectedStyle")
|
||||
protected String selectedStyle;
|
||||
|
||||
@XmlAttribute(name = "StyleName")
|
||||
protected String styleName;
|
||||
|
||||
@XmlAttribute(name = "URI")
|
||||
protected String uri;
|
||||
|
||||
public List<CTSourceType> getSource() {
|
||||
if (this.source == null)
|
||||
this.source = new ArrayList<CTSourceType>();
|
||||
return this.source;
|
||||
}
|
||||
|
||||
public String getSelectedStyle() {
|
||||
return this.selectedStyle;
|
||||
}
|
||||
|
||||
public void setSelectedStyle(String value) {
|
||||
this.selectedStyle = value;
|
||||
}
|
||||
|
||||
public String getStyleName() {
|
||||
return this.styleName;
|
||||
}
|
||||
|
||||
public void setStyleName(String value) {
|
||||
this.styleName = value;
|
||||
}
|
||||
|
||||
public String getURI() {
|
||||
return this.uri;
|
||||
}
|
||||
|
||||
public void setURI(String value) {
|
||||
this.uri = value;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,518 @@
|
|||
package org.docx4j.bibliography;
|
||||
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.bind.annotation.XmlElementDecl;
|
||||
import javax.xml.bind.annotation.XmlRegistry;
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
@XmlRegistry
|
||||
public class ObjectFactory {
|
||||
private static final QName _Sources_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Sources");
|
||||
|
||||
private static final QName _CTAuthorTypeEditor_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Editor");
|
||||
|
||||
private static final QName _CTAuthorTypeInventor_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Inventor");
|
||||
|
||||
private static final QName _CTAuthorTypeInterviewee_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Interviewee");
|
||||
|
||||
private static final QName _CTAuthorTypeBookAuthor_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "BookAuthor");
|
||||
|
||||
private static final QName _CTAuthorTypeProducerName_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "ProducerName");
|
||||
|
||||
private static final QName _CTAuthorTypeInterviewer_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Interviewer");
|
||||
|
||||
private static final QName _CTAuthorTypeAuthor_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Author");
|
||||
|
||||
private static final QName _CTAuthorTypePerformer_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Performer");
|
||||
|
||||
private static final QName _CTAuthorTypeCompiler_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Compiler");
|
||||
|
||||
private static final QName _CTAuthorTypeCounsel_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Counsel");
|
||||
|
||||
private static final QName _CTAuthorTypeWriter_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Writer");
|
||||
|
||||
private static final QName _CTAuthorTypeConductor_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Conductor");
|
||||
|
||||
private static final QName _CTAuthorTypeComposer_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Composer");
|
||||
|
||||
private static final QName _CTAuthorTypeArtist_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Artist");
|
||||
|
||||
private static final QName _CTAuthorTypeDirector_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Director");
|
||||
|
||||
private static final QName _CTAuthorTypeTranslator_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Translator");
|
||||
|
||||
private static final QName _CTSourceTypeComments_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Comments");
|
||||
|
||||
private static final QName _CTSourceTypeInternetSiteTitle_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "InternetSiteTitle");
|
||||
|
||||
private static final QName _CTSourceTypePages_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Pages");
|
||||
|
||||
private static final QName _CTSourceTypeProductionCompany_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "ProductionCompany");
|
||||
|
||||
private static final QName _CTSourceTypeDistributor_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Distributor");
|
||||
|
||||
private static final QName _CTSourceTypePublisher_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Publisher");
|
||||
|
||||
private static final QName _CTSourceTypePatentNumber_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "PatentNumber");
|
||||
|
||||
private static final QName _CTSourceTypeTheater_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Theater");
|
||||
|
||||
private static final QName _CTSourceTypeThesisType_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "ThesisType");
|
||||
|
||||
private static final QName _CTSourceTypeAlbumTitle_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "AlbumTitle");
|
||||
|
||||
private static final QName _CTSourceTypeMonth_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Month");
|
||||
|
||||
private static final QName _CTSourceTypeYearAccessed_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "YearAccessed");
|
||||
|
||||
private static final QName _CTSourceTypeConferenceName_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "ConferenceName");
|
||||
|
||||
private static final QName _CTSourceTypeRecordingNumber_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "RecordingNumber");
|
||||
|
||||
private static final QName _CTSourceTypeBookTitle_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "BookTitle");
|
||||
|
||||
private static final QName _CTSourceTypeGuid_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Guid");
|
||||
|
||||
private static final QName _CTSourceTypeIssue_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Issue");
|
||||
|
||||
private static final QName _CTSourceTypeTag_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Tag");
|
||||
|
||||
private static final QName _CTSourceTypeCaseNumber_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "CaseNumber");
|
||||
|
||||
private static final QName _CTSourceTypeVersion_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Version");
|
||||
|
||||
private static final QName _CTSourceTypeReporter_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Reporter");
|
||||
|
||||
private static final QName _CTSourceTypeMedium_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Medium");
|
||||
|
||||
private static final QName _CTSourceTypeBroadcaster_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Broadcaster");
|
||||
|
||||
private static final QName _CTSourceTypeLCID_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "LCID");
|
||||
|
||||
private static final QName _CTSourceTypeBroadcastTitle_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "BroadcastTitle");
|
||||
|
||||
private static final QName _CTSourceTypeSourceType_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "SourceType");
|
||||
|
||||
private static final QName _CTSourceTypeVolume_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Volume");
|
||||
|
||||
private static final QName _CTSourceTypeMonthAccessed_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "MonthAccessed");
|
||||
|
||||
private static final QName _CTSourceTypeJournalName_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "JournalName");
|
||||
|
||||
private static final QName _CTSourceTypeInstitution_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Institution");
|
||||
|
||||
private static final QName _CTSourceTypeTitle_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Title");
|
||||
|
||||
private static final QName _CTSourceTypeCity_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "City");
|
||||
|
||||
private static final QName _CTSourceTypeEdition_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Edition");
|
||||
|
||||
private static final QName _CTSourceTypeStandardNumber_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "StandardNumber");
|
||||
|
||||
private static final QName _CTSourceTypeRefOrder_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "RefOrder");
|
||||
|
||||
private static final QName _CTSourceTypeShortTitle_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "ShortTitle");
|
||||
|
||||
private static final QName _CTSourceTypeAbbreviatedCaseNumber_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "AbbreviatedCaseNumber");
|
||||
|
||||
private static final QName _CTSourceTypeType_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Type");
|
||||
|
||||
private static final QName _CTSourceTypeCountryRegion_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "CountryRegion");
|
||||
|
||||
private static final QName _CTSourceTypeChapterNumber_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "ChapterNumber");
|
||||
|
||||
private static final QName _CTSourceTypePublicationTitle_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "PublicationTitle");
|
||||
|
||||
private static final QName _CTSourceTypePeriodicalTitle_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "PeriodicalTitle");
|
||||
|
||||
private static final QName _CTSourceTypeDay_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Day");
|
||||
|
||||
private static final QName _CTSourceTypeDayAccessed_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "DayAccessed");
|
||||
|
||||
private static final QName _CTSourceTypeYear_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Year");
|
||||
|
||||
private static final QName _CTSourceTypeStation_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Station");
|
||||
|
||||
private static final QName _CTSourceTypeNumberVolumes_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "NumberVolumes");
|
||||
|
||||
private static final QName _CTSourceTypeStateProvince_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "StateProvince");
|
||||
|
||||
private static final QName _CTSourceTypeURL_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "URL");
|
||||
|
||||
private static final QName _CTSourceTypeCourt_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Court");
|
||||
|
||||
private static final QName _CTSourceTypeDepartment_QNAME = new QName("http://schemas.openxmlformats.org/officeDocument/2006/bibliography", "Department");
|
||||
|
||||
public CTAuthorType createCTAuthorType() {
|
||||
return new CTAuthorType();
|
||||
}
|
||||
|
||||
public CTNameListType createCTNameListType() {
|
||||
return new CTNameListType();
|
||||
}
|
||||
|
||||
public CTSources createCTSources() {
|
||||
return new CTSources();
|
||||
}
|
||||
|
||||
public CTPersonType createCTPersonType() {
|
||||
return new CTPersonType();
|
||||
}
|
||||
|
||||
public CTNameOrCorporateType createCTNameOrCorporateType() {
|
||||
return new CTNameOrCorporateType();
|
||||
}
|
||||
|
||||
public CTNameType createCTNameType() {
|
||||
return new CTNameType();
|
||||
}
|
||||
|
||||
public CTSourceType createCTSourceType() {
|
||||
return new CTSourceType();
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Sources")
|
||||
public JAXBElement<CTSources> createSources(CTSources value) {
|
||||
return new JAXBElement(_Sources_QNAME, CTSources.class, null, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Editor", scope = CTAuthorType.class)
|
||||
public JAXBElement<CTNameType> createCTAuthorTypeEditor(CTNameType value) {
|
||||
return new JAXBElement(_CTAuthorTypeEditor_QNAME, CTNameType.class, CTAuthorType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Inventor", scope = CTAuthorType.class)
|
||||
public JAXBElement<CTNameType> createCTAuthorTypeInventor(CTNameType value) {
|
||||
return new JAXBElement(_CTAuthorTypeInventor_QNAME, CTNameType.class, CTAuthorType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Interviewee", scope = CTAuthorType.class)
|
||||
public JAXBElement<CTNameType> createCTAuthorTypeInterviewee(CTNameType value) {
|
||||
return new JAXBElement(_CTAuthorTypeInterviewee_QNAME, CTNameType.class, CTAuthorType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "BookAuthor", scope = CTAuthorType.class)
|
||||
public JAXBElement<CTNameType> createCTAuthorTypeBookAuthor(CTNameType value) {
|
||||
return new JAXBElement(_CTAuthorTypeBookAuthor_QNAME, CTNameType.class, CTAuthorType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "ProducerName", scope = CTAuthorType.class)
|
||||
public JAXBElement<CTNameType> createCTAuthorTypeProducerName(CTNameType value) {
|
||||
return new JAXBElement(_CTAuthorTypeProducerName_QNAME, CTNameType.class, CTAuthorType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Interviewer", scope = CTAuthorType.class)
|
||||
public JAXBElement<CTNameType> createCTAuthorTypeInterviewer(CTNameType value) {
|
||||
return new JAXBElement(_CTAuthorTypeInterviewer_QNAME, CTNameType.class, CTAuthorType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Author", scope = CTAuthorType.class)
|
||||
public JAXBElement<CTNameOrCorporateType> createCTAuthorTypeAuthor(CTNameOrCorporateType value) {
|
||||
return new JAXBElement(_CTAuthorTypeAuthor_QNAME, CTNameOrCorporateType.class, CTAuthorType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Performer", scope = CTAuthorType.class)
|
||||
public JAXBElement<CTNameOrCorporateType> createCTAuthorTypePerformer(CTNameOrCorporateType value) {
|
||||
return new JAXBElement(_CTAuthorTypePerformer_QNAME, CTNameOrCorporateType.class, CTAuthorType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Compiler", scope = CTAuthorType.class)
|
||||
public JAXBElement<CTNameType> createCTAuthorTypeCompiler(CTNameType value) {
|
||||
return new JAXBElement(_CTAuthorTypeCompiler_QNAME, CTNameType.class, CTAuthorType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Counsel", scope = CTAuthorType.class)
|
||||
public JAXBElement<CTNameType> createCTAuthorTypeCounsel(CTNameType value) {
|
||||
return new JAXBElement(_CTAuthorTypeCounsel_QNAME, CTNameType.class, CTAuthorType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Writer", scope = CTAuthorType.class)
|
||||
public JAXBElement<CTNameType> createCTAuthorTypeWriter(CTNameType value) {
|
||||
return new JAXBElement(_CTAuthorTypeWriter_QNAME, CTNameType.class, CTAuthorType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Conductor", scope = CTAuthorType.class)
|
||||
public JAXBElement<CTNameType> createCTAuthorTypeConductor(CTNameType value) {
|
||||
return new JAXBElement(_CTAuthorTypeConductor_QNAME, CTNameType.class, CTAuthorType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Composer", scope = CTAuthorType.class)
|
||||
public JAXBElement<CTNameType> createCTAuthorTypeComposer(CTNameType value) {
|
||||
return new JAXBElement(_CTAuthorTypeComposer_QNAME, CTNameType.class, CTAuthorType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Artist", scope = CTAuthorType.class)
|
||||
public JAXBElement<CTNameType> createCTAuthorTypeArtist(CTNameType value) {
|
||||
return new JAXBElement(_CTAuthorTypeArtist_QNAME, CTNameType.class, CTAuthorType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Director", scope = CTAuthorType.class)
|
||||
public JAXBElement<CTNameType> createCTAuthorTypeDirector(CTNameType value) {
|
||||
return new JAXBElement(_CTAuthorTypeDirector_QNAME, CTNameType.class, CTAuthorType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Translator", scope = CTAuthorType.class)
|
||||
public JAXBElement<CTNameType> createCTAuthorTypeTranslator(CTNameType value) {
|
||||
return new JAXBElement(_CTAuthorTypeTranslator_QNAME, CTNameType.class, CTAuthorType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Comments", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeComments(String value) {
|
||||
return new JAXBElement(_CTSourceTypeComments_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "InternetSiteTitle", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeInternetSiteTitle(String value) {
|
||||
return new JAXBElement(_CTSourceTypeInternetSiteTitle_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Pages", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypePages(String value) {
|
||||
return new JAXBElement(_CTSourceTypePages_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "ProductionCompany", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeProductionCompany(String value) {
|
||||
return new JAXBElement(_CTSourceTypeProductionCompany_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Distributor", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeDistributor(String value) {
|
||||
return new JAXBElement(_CTSourceTypeDistributor_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Publisher", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypePublisher(String value) {
|
||||
return new JAXBElement(_CTSourceTypePublisher_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "PatentNumber", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypePatentNumber(String value) {
|
||||
return new JAXBElement(_CTSourceTypePatentNumber_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Theater", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeTheater(String value) {
|
||||
return new JAXBElement(_CTSourceTypeTheater_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "ThesisType", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeThesisType(String value) {
|
||||
return new JAXBElement(_CTSourceTypeThesisType_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "AlbumTitle", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeAlbumTitle(String value) {
|
||||
return new JAXBElement(_CTSourceTypeAlbumTitle_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Month", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeMonth(String value) {
|
||||
return new JAXBElement(_CTSourceTypeMonth_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "YearAccessed", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeYearAccessed(String value) {
|
||||
return new JAXBElement(_CTSourceTypeYearAccessed_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "ConferenceName", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeConferenceName(String value) {
|
||||
return new JAXBElement(_CTSourceTypeConferenceName_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "RecordingNumber", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeRecordingNumber(String value) {
|
||||
return new JAXBElement(_CTSourceTypeRecordingNumber_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "BookTitle", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeBookTitle(String value) {
|
||||
return new JAXBElement(_CTSourceTypeBookTitle_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Guid", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeGuid(String value) {
|
||||
return new JAXBElement(_CTSourceTypeGuid_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Issue", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeIssue(String value) {
|
||||
return new JAXBElement(_CTSourceTypeIssue_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Tag", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeTag(String value) {
|
||||
return new JAXBElement(_CTSourceTypeTag_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "CaseNumber", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeCaseNumber(String value) {
|
||||
return new JAXBElement(_CTSourceTypeCaseNumber_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Version", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeVersion(String value) {
|
||||
return new JAXBElement(_CTSourceTypeVersion_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Reporter", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeReporter(String value) {
|
||||
return new JAXBElement(_CTSourceTypeReporter_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Medium", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeMedium(String value) {
|
||||
return new JAXBElement(_CTSourceTypeMedium_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Broadcaster", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeBroadcaster(String value) {
|
||||
return new JAXBElement(_CTSourceTypeBroadcaster_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "LCID", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeLCID(String value) {
|
||||
return new JAXBElement(_CTSourceTypeLCID_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "BroadcastTitle", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeBroadcastTitle(String value) {
|
||||
return new JAXBElement(_CTSourceTypeBroadcastTitle_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "SourceType", scope = CTSourceType.class)
|
||||
public JAXBElement<STSourceType> createCTSourceTypeSourceType(STSourceType value) {
|
||||
return new JAXBElement(_CTSourceTypeSourceType_QNAME, STSourceType.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Volume", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeVolume(String value) {
|
||||
return new JAXBElement(_CTSourceTypeVolume_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "MonthAccessed", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeMonthAccessed(String value) {
|
||||
return new JAXBElement(_CTSourceTypeMonthAccessed_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "JournalName", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeJournalName(String value) {
|
||||
return new JAXBElement(_CTSourceTypeJournalName_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Institution", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeInstitution(String value) {
|
||||
return new JAXBElement(_CTSourceTypeInstitution_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Title", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeTitle(String value) {
|
||||
return new JAXBElement(_CTSourceTypeTitle_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "City", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeCity(String value) {
|
||||
return new JAXBElement(_CTSourceTypeCity_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Edition", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeEdition(String value) {
|
||||
return new JAXBElement(_CTSourceTypeEdition_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "StandardNumber", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeStandardNumber(String value) {
|
||||
return new JAXBElement(_CTSourceTypeStandardNumber_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "RefOrder", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeRefOrder(String value) {
|
||||
return new JAXBElement(_CTSourceTypeRefOrder_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "ShortTitle", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeShortTitle(String value) {
|
||||
return new JAXBElement(_CTSourceTypeShortTitle_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "AbbreviatedCaseNumber", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeAbbreviatedCaseNumber(String value) {
|
||||
return new JAXBElement(_CTSourceTypeAbbreviatedCaseNumber_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Type", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeType(String value) {
|
||||
return new JAXBElement(_CTSourceTypeType_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "CountryRegion", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeCountryRegion(String value) {
|
||||
return new JAXBElement(_CTSourceTypeCountryRegion_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "ChapterNumber", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeChapterNumber(String value) {
|
||||
return new JAXBElement(_CTSourceTypeChapterNumber_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Author", scope = CTSourceType.class)
|
||||
public JAXBElement<CTAuthorType> createCTSourceTypeAuthor(CTAuthorType value) {
|
||||
return new JAXBElement(_CTAuthorTypeAuthor_QNAME, CTAuthorType.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "PublicationTitle", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypePublicationTitle(String value) {
|
||||
return new JAXBElement(_CTSourceTypePublicationTitle_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "PeriodicalTitle", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypePeriodicalTitle(String value) {
|
||||
return new JAXBElement(_CTSourceTypePeriodicalTitle_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Day", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeDay(String value) {
|
||||
return new JAXBElement(_CTSourceTypeDay_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "DayAccessed", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeDayAccessed(String value) {
|
||||
return new JAXBElement(_CTSourceTypeDayAccessed_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Year", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeYear(String value) {
|
||||
return new JAXBElement(_CTSourceTypeYear_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Station", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeStation(String value) {
|
||||
return new JAXBElement(_CTSourceTypeStation_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "NumberVolumes", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeNumberVolumes(String value) {
|
||||
return new JAXBElement(_CTSourceTypeNumberVolumes_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "StateProvince", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeStateProvince(String value) {
|
||||
return new JAXBElement(_CTSourceTypeStateProvince_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "URL", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeURL(String value) {
|
||||
return new JAXBElement(_CTSourceTypeURL_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Court", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeCourt(String value) {
|
||||
return new JAXBElement(_CTSourceTypeCourt_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
|
||||
@XmlElementDecl(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", name = "Department", scope = CTSourceType.class)
|
||||
public JAXBElement<String> createCTSourceTypeDepartment(String value) {
|
||||
return new JAXBElement(_CTSourceTypeDepartment_QNAME, String.class, CTSourceType.class, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package org.docx4j.bibliography;
|
||||
|
||||
import javax.xml.bind.annotation.XmlEnum;
|
||||
import javax.xml.bind.annotation.XmlEnumValue;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
@XmlType(name = "ST_SourceType")
|
||||
@XmlEnum
|
||||
public enum STSourceType {
|
||||
ARTICLE_IN_A_PERIODICAL("ArticleInAPeriodical"),
|
||||
BOOK("Book"),
|
||||
BOOK_SECTION("BookSection"),
|
||||
JOURNAL_ARTICLE("JournalArticle"),
|
||||
CONFERENCE_PROCEEDINGS("ConferenceProceedings"),
|
||||
REPORT("Report"),
|
||||
SOUND_RECORDING("SoundRecording"),
|
||||
PERFORMANCE("Performance"),
|
||||
ART("Art"),
|
||||
DOCUMENT_FROM_INTERNET_SITE("DocumentFromInternetSite"),
|
||||
INTERNET_SITE("InternetSite"),
|
||||
FILM("Film"),
|
||||
INTERVIEW("Interview"),
|
||||
PATENT("Patent"),
|
||||
ELECTRONIC_SOURCE("ElectronicSource"),
|
||||
CASE("Case"),
|
||||
MISC("Misc");
|
||||
|
||||
private final String value;
|
||||
|
||||
STSourceType(String v) {
|
||||
this.value = v;
|
||||
}
|
||||
|
||||
public String value() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public static STSourceType fromValue(String v) {
|
||||
for (STSourceType c : values()) {
|
||||
if (c.value.equals(v))
|
||||
return c;
|
||||
}
|
||||
throw new IllegalArgumentException(v);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package org.docx4j.bibliography;
|
||||
|
||||
import javax.xml.bind.annotation.XmlNsForm;
|
||||
import javax.xml.bind.annotation.XmlSchema;
|
||||
|
||||
@XmlSchema(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", elementFormDefault = XmlNsForm.QUALIFIED)
|
||||
interface package-info {}
|
||||
201
rus/WEB-INF/lib/docx4j-3.2.1_src/org/docx4j/convert/in/Doc.java
Normal file
201
rus/WEB-INF/lib/docx4j-3.2.1_src/org/docx4j/convert/in/Doc.java
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
package org.docx4j.convert.in;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import org.apache.poi.hwpf.HWPFDocument;
|
||||
import org.apache.poi.hwpf.model.DocumentProperties;
|
||||
import org.apache.poi.hwpf.model.ListTables;
|
||||
import org.apache.poi.hwpf.model.StyleSheet;
|
||||
import org.apache.poi.hwpf.usermodel.CharacterRun;
|
||||
import org.apache.poi.hwpf.usermodel.Paragraph;
|
||||
import org.apache.poi.hwpf.usermodel.Picture;
|
||||
import org.apache.poi.hwpf.usermodel.Range;
|
||||
import org.apache.poi.hwpf.usermodel.Section;
|
||||
import org.apache.poi.hwpf.usermodel.Table;
|
||||
import org.apache.poi.hwpf.usermodel.TableCell;
|
||||
import org.apache.poi.hwpf.usermodel.TableRow;
|
||||
import org.docx4j.UnitsOfMeasurement;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.dml.wordprocessingDrawing.Inline;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
|
||||
import org.docx4j.wml.BooleanDefaultTrue;
|
||||
import org.docx4j.wml.Drawing;
|
||||
import org.docx4j.wml.ObjectFactory;
|
||||
import org.docx4j.wml.P;
|
||||
import org.docx4j.wml.R;
|
||||
import org.docx4j.wml.RPr;
|
||||
import org.docx4j.wml.Tbl;
|
||||
import org.docx4j.wml.TblGrid;
|
||||
import org.docx4j.wml.TblPr;
|
||||
import org.docx4j.wml.Tc;
|
||||
import org.docx4j.wml.Text;
|
||||
import org.docx4j.wml.Tr;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Doc {
|
||||
private static Logger log = LoggerFactory.getLogger(Doc.class);
|
||||
|
||||
public static WordprocessingMLPackage convert(InputStream in) throws Exception {
|
||||
HWPFDocument doc = new HWPFDocument(in);
|
||||
WordprocessingMLPackage out = WordprocessingMLPackage.createPackage();
|
||||
convert(doc, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
private static void convert(HWPFDocument doc, WordprocessingMLPackage wordMLPackage) throws Exception {
|
||||
StyleSheet stylesheet = doc.getStyleSheet();
|
||||
ListTables listTables = doc.getListTables();
|
||||
DocumentProperties docProps = doc.getDocProperties();
|
||||
MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();
|
||||
ObjectFactory factory = new ObjectFactory();
|
||||
Range r = doc.getRange();
|
||||
for (int x = 0; x < r.numSections(); x++) {
|
||||
Section s = r.getSection(x);
|
||||
for (int y = 0; y < s.numParagraphs(); y++) {
|
||||
Paragraph p = s.getParagraph(y);
|
||||
if (p.isInTable()) {
|
||||
Table t = s.getTable(p);
|
||||
int cl = numCol(t);
|
||||
log.info("Found " + t.numRows() + "x" + cl + " table - TODO - convert");
|
||||
handleTable(wordMLPackage, doc, t, stylesheet, documentPart, factory);
|
||||
y += t.numParagraphs() - 1;
|
||||
} else {
|
||||
P paraToAdd = handleP(wordMLPackage, doc, p, stylesheet, documentPart, factory);
|
||||
documentPart.addObject(paraToAdd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int ID1 = 1;
|
||||
|
||||
private static int ID2 = 2;
|
||||
|
||||
private static P handleP(WordprocessingMLPackage wordMLPackage, HWPFDocument doc, Paragraph p, StyleSheet stylesheet, MainDocumentPart documentPart, ObjectFactory factory) {
|
||||
P wmlP = null;
|
||||
if (p.getStyleIndex() > 0) {
|
||||
log.debug("Styled paragraph, with index: " + p.getStyleIndex());
|
||||
String styleName = stylesheet.getStyleDescription(p.getStyleIndex()).getName();
|
||||
log.debug(styleName);
|
||||
wmlP = documentPart.createStyledParagraphOfText(stripSpace(styleName), null);
|
||||
} else {
|
||||
wmlP = documentPart.createParagraphOfText(null);
|
||||
}
|
||||
for (int z = 0; z < p.numCharacterRuns(); z++) {
|
||||
CharacterRun run = p.getCharacterRun(z);
|
||||
RPr rPr = null;
|
||||
if (run.isBold()) {
|
||||
if (rPr == null)
|
||||
rPr = factory.createRPr();
|
||||
BooleanDefaultTrue boldOn = factory.createBooleanDefaultTrue();
|
||||
boldOn.setVal(Boolean.TRUE);
|
||||
rPr.setB(boldOn);
|
||||
}
|
||||
if (doc instanceof HWPFDocument && doc.getPicturesTable().hasPicture(run)) {
|
||||
Picture picture = doc.getPicturesTable().extractPicture(run, true);
|
||||
try {
|
||||
BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMLPackage, picture.getContent());
|
||||
long cx = UnitsOfMeasurement.twipToEMU((double)Math.round((double)imagePart.getImageInfo().getSize().getWidthMpt() * (double)picture.getHorizontalScalingFactor() * 1.0E-5D)) * 2L;
|
||||
long cy = UnitsOfMeasurement.twipToEMU((double)Math.round((double)imagePart.getImageInfo().getSize().getHeightMpt() * (double)picture.getVerticalScalingFactor() * 1.0E-5D)) * 2L;
|
||||
Inline inline = imagePart.createImageInline(null, "", ID1++, ID2++, cx, cy, false);
|
||||
R imgrun = factory.createR();
|
||||
Drawing drawing = factory.createDrawing();
|
||||
imgrun.getContent().add(drawing);
|
||||
drawing.getAnchorOrInline().add(inline);
|
||||
wmlP.getContent().add(imgrun);
|
||||
} catch (Exception e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
String text = run.text();
|
||||
log.debug("Processing: " + text);
|
||||
String cleansed = stripNonValidXMLCharacters(text);
|
||||
if (!text.equals(cleansed))
|
||||
log.warn("Cleansed..");
|
||||
Text t = factory.createText();
|
||||
t.setValue(cleansed);
|
||||
R wmlRun = factory.createR();
|
||||
if (rPr != null)
|
||||
wmlRun.setRPr(rPr);
|
||||
wmlRun.getRunContent().add(t);
|
||||
wmlP.getParagraphContent().add(wmlRun);
|
||||
}
|
||||
}
|
||||
System.out.println(XmlUtils.marshaltoString(wmlP, true, true));
|
||||
return wmlP;
|
||||
}
|
||||
|
||||
private static String stripSpace(String in) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = 0; i < in.length(); i++) {
|
||||
if (in.charAt(i) != ' ')
|
||||
sb.append(in.charAt(i));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static void addTODO(ObjectFactory factory, P wmlP, String message) {
|
||||
Text t = factory.createText();
|
||||
t.setValue(message);
|
||||
R wmlRun = factory.createR();
|
||||
wmlRun.getRunContent().add(t);
|
||||
wmlP.getParagraphContent().add(wmlRun);
|
||||
}
|
||||
|
||||
public static String stripNonValidXMLCharacters(String in) {
|
||||
StringBuffer out = new StringBuffer();
|
||||
if (in == null || "".equals(in))
|
||||
return "";
|
||||
for (int i = 0; i < in.length(); i++) {
|
||||
char current = in.charAt(i);
|
||||
if (current == '\t' || current == '\n' || current == '\r' || (current >= ' ' && current <= '') || (current >= '' && current <= '<27>') || (current >= 65536 && current <= 1114111)) {
|
||||
out.append(current);
|
||||
} else {
|
||||
out.append("[#?]");
|
||||
}
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
private static int numCol(Table t) {
|
||||
int col = 0;
|
||||
for (int i = 0; i < t.numRows(); i++) {
|
||||
if (t.getRow(i).numCells() > col)
|
||||
col = t.getRow(i).numCells();
|
||||
}
|
||||
return col;
|
||||
}
|
||||
|
||||
private static void handleTable(WordprocessingMLPackage wordMLPackage, HWPFDocument doc, Table t, StyleSheet stylesheet, MainDocumentPart documentPart, ObjectFactory factory) {
|
||||
Tbl tbl = factory.createTbl();
|
||||
documentPart.addObject(tbl);
|
||||
TblPr tblPr = factory.createTblPr();
|
||||
tbl.setTblPr(tblPr);
|
||||
TblGrid tblGrid = factory.createTblGrid();
|
||||
tbl.setTblGrid(tblGrid);
|
||||
for (int i = 0; i < t.numRows(); i++) {
|
||||
TableRow tr = t.getRow(i);
|
||||
Tr trOut = factory.createTr();
|
||||
tbl.getEGContentRowContent().add(trOut);
|
||||
for (int j = 0; j < tr.numCells(); j++) {
|
||||
TableCell tc = tr.getCell(j);
|
||||
Tc tcOut = factory.createTc();
|
||||
trOut.getEGContentCellContent().add(tcOut);
|
||||
for (int y = 0; y < tc.numParagraphs(); y++) {
|
||||
Paragraph p = tc.getParagraph(y);
|
||||
P paraToAdd = handleP(wordMLPackage, doc, p, stylesheet, documentPart, factory);
|
||||
tcOut.getEGBlockLevelElts().add(paraToAdd);
|
||||
log.debug("Added p to tc");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String localPath = System.getProperty("user.dir") + "/LineSpacing.doc";
|
||||
WordprocessingMLPackage out = convert(new FileInputStream(localPath));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,328 @@
|
|||
package org.docx4j.convert.in;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.HashMap;
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.UnmarshalException;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.bibliography.CTSources;
|
||||
import org.docx4j.convert.out.flatOpcXml.FlatOpcXmlCreator;
|
||||
import org.docx4j.docProps.coverPageProps.CoverPageProperties;
|
||||
import org.docx4j.jaxb.Context;
|
||||
import org.docx4j.jaxb.JaxbValidationEventHandler;
|
||||
import org.docx4j.model.datastorage.CustomXmlDataStorage;
|
||||
import org.docx4j.openpackaging.Base;
|
||||
import org.docx4j.openpackaging.URIHelper;
|
||||
import org.docx4j.openpackaging.contenttype.ContentType;
|
||||
import org.docx4j.openpackaging.contenttype.ContentTypeManager;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.openpackaging.exceptions.InvalidFormatException;
|
||||
import org.docx4j.openpackaging.exceptions.PartUnrecognisedException;
|
||||
import org.docx4j.openpackaging.io.Load;
|
||||
import org.docx4j.openpackaging.packages.OpcPackage;
|
||||
import org.docx4j.openpackaging.packages.PresentationMLPackage;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.openpackaging.parts.CustomXmlDataStoragePart;
|
||||
import org.docx4j.openpackaging.parts.DocPropsCoverPagePart;
|
||||
import org.docx4j.openpackaging.parts.JaxbXmlPart;
|
||||
import org.docx4j.openpackaging.parts.PartName;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.BibliographyPart;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPart;
|
||||
import org.docx4j.openpackaging.parts.XmlPart;
|
||||
import org.docx4j.openpackaging.parts.opendope.ComponentsPart;
|
||||
import org.docx4j.openpackaging.parts.opendope.ConditionsPart;
|
||||
import org.docx4j.openpackaging.parts.opendope.QuestionsPart;
|
||||
import org.docx4j.openpackaging.parts.opendope.StandardisedAnswersPart;
|
||||
import org.docx4j.openpackaging.parts.opendope.XPathsPart;
|
||||
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
|
||||
import org.docx4j.relationships.Relationship;
|
||||
import org.docx4j.xmlPackage.Package;
|
||||
import org.docx4j.xmlPackage.Part;
|
||||
import org.opendope.answers.Answers;
|
||||
import org.opendope.components.Components;
|
||||
import org.opendope.conditions.Conditions;
|
||||
import org.opendope.questions.Questionnaire;
|
||||
import org.opendope.xpaths.Xpaths;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.DOMException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
public class FlatOpcXmlImporter {
|
||||
private static Logger log = LoggerFactory.getLogger(FlatOpcXmlImporter.class);
|
||||
|
||||
private HashMap<String, Part> parts;
|
||||
|
||||
private ContentTypeManager ctm;
|
||||
|
||||
public FlatOpcXmlImporter(InputStream is) throws JAXBException {
|
||||
JAXBContext jc = Context.jcXmlPackage;
|
||||
Unmarshaller u = jc.createUnmarshaller();
|
||||
u.setEventHandler(new JaxbValidationEventHandler());
|
||||
Package flatOpcXml = null;
|
||||
try {
|
||||
flatOpcXml = (Package)XmlUtils.unwrap(u.unmarshal(new StreamSource(is)));
|
||||
} catch (UnmarshalException e) {
|
||||
if (e.getMessage().contains("http://schemas.microsoft.com/office/word/2003/wordml"))
|
||||
throw new IllegalArgumentException("Word 2003 XML is not supported. Use a docx or Flat OPC XML instead, or look at the Word2003XmlConverter proof of concept.");
|
||||
throw e;
|
||||
}
|
||||
init(flatOpcXml);
|
||||
}
|
||||
|
||||
public FlatOpcXmlImporter(Package flatOpcXml) {
|
||||
init(flatOpcXml);
|
||||
}
|
||||
|
||||
private void init(Package flatOpcXml) {
|
||||
this.parts = new HashMap<String, Part>();
|
||||
for (Part p : flatOpcXml.getPart())
|
||||
this.parts.put(p.getName(), p);
|
||||
}
|
||||
|
||||
protected HashMap<String, String> handled = new HashMap<String, String>();
|
||||
|
||||
private OpcPackage packageResult;
|
||||
|
||||
public OpcPackage get() throws Docx4JException {
|
||||
this.ctm = new ContentTypeManager();
|
||||
this.ctm.addDefaultContentType("rels", "application/vnd.openxmlformats-package.relationships+xml");
|
||||
this.ctm.addDefaultContentType("xml", "application/xml");
|
||||
if (this.parts.get("/word/document.xml") != null) {
|
||||
this.packageResult = new WordprocessingMLPackage(this.ctm);
|
||||
} else if (this.parts.get("/ppt/presentation.xml") != null) {
|
||||
this.packageResult = new PresentationMLPackage(this.ctm);
|
||||
} else {
|
||||
throw new Docx4JException("Unrecognised package");
|
||||
}
|
||||
log.info("Creating " + this.packageResult.getClass().getName());
|
||||
String partName = "/_rels/.rels";
|
||||
RelationshipsPart rp = getRelationshipsPartFromXmlPackage(this.packageResult, partName);
|
||||
this.packageResult.setRelationships(rp);
|
||||
log.info("Object created for: " + partName);
|
||||
addPartsFromRelationships(this.packageResult, rp);
|
||||
Load.registerCustomXmlDataStorageParts(this.packageResult);
|
||||
return this.packageResult;
|
||||
}
|
||||
|
||||
private RelationshipsPart getRelationshipsPartFromXmlPackage(Base p, String partName) throws Docx4JException {
|
||||
RelationshipsPart rp = null;
|
||||
try {
|
||||
Part part = this.parts.get(partName);
|
||||
if (part == null)
|
||||
return null;
|
||||
rp = p.getRelationshipsPart(true);
|
||||
populateRelationshipsPart(rp, part.getXmlData().getAny());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new Docx4JException("Error getting document from XmlPackage:" + partName, e);
|
||||
}
|
||||
return rp;
|
||||
}
|
||||
|
||||
public static RelationshipsPart populateRelationshipsPart(RelationshipsPart rp, Element el) throws InvalidFormatException, JAXBException {
|
||||
rp.setRelationships(rp.unmarshal(el));
|
||||
return rp;
|
||||
}
|
||||
|
||||
private void addPartsFromRelationships(Base source, RelationshipsPart rp) throws Docx4JException {
|
||||
OpcPackage pkg = source.getPackage();
|
||||
for (Relationship r : rp.getRelationships().getRelationship()) {
|
||||
log.debug("For Relationship Id=" + r.getId() + " Source is " + rp.getSourceP().getPartName() + ", Target is " + r.getTarget());
|
||||
try {
|
||||
getPart(pkg, rp, r);
|
||||
} catch (Exception e) {
|
||||
throw new Docx4JException("Failed to add parts from relationships", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void getPart(OpcPackage pkg, RelationshipsPart rp, Relationship r) throws Docx4JException, InvalidFormatException, URISyntaxException {
|
||||
Base source = null;
|
||||
String resolvedPartUri = null;
|
||||
if (r.getTargetMode() == null || !r.getTargetMode().equals("External")) {
|
||||
source = rp.getSourceP();
|
||||
resolvedPartUri = URIHelper.resolvePartUri(rp.getSourceURI(), new URI(r.getTarget())).toString();
|
||||
} else {
|
||||
log.info("Encountered external resource " + r.getTarget() + " of type " + r.getType());
|
||||
return;
|
||||
}
|
||||
if (this.handled.get(resolvedPartUri) != null)
|
||||
return;
|
||||
String relationshipType = r.getType();
|
||||
org.docx4j.openpackaging.parts.Part part = getRawPart(this.ctm, resolvedPartUri, r);
|
||||
rp.loadPart(part, r);
|
||||
this.handled.put(resolvedPartUri, resolvedPartUri);
|
||||
if (source.setPartShortcut(part, relationshipType))
|
||||
log.debug("Convenience method established from " + source.getPartName() + " to " + part.getPartName());
|
||||
RelationshipsPart rrp = getRelationshipsPart(part);
|
||||
if (rrp != null)
|
||||
addPartsFromRelationships(part, rrp);
|
||||
}
|
||||
|
||||
public RelationshipsPart getRelationshipsPart(org.docx4j.openpackaging.parts.Part part) throws Docx4JException, InvalidFormatException {
|
||||
String relPart = PartName.getRelationshipsPartName(part.getPartName().getName());
|
||||
RelationshipsPart rrp = getRelationshipsPartFromXmlPackage(part, relPart);
|
||||
if (rrp != null) {
|
||||
part.setRelationships(rrp);
|
||||
} else {
|
||||
log.debug("No relationships " + relPart);
|
||||
return null;
|
||||
}
|
||||
return rrp;
|
||||
}
|
||||
|
||||
public org.docx4j.openpackaging.parts.Part getRawPart(ContentTypeManager ctm, String resolvedPartUri, Relationship rel) throws Docx4JException {
|
||||
Part pkgPart = this.parts.get(resolvedPartUri);
|
||||
if (pkgPart == null) {
|
||||
log.error("Missing part: " + resolvedPartUri);
|
||||
return null;
|
||||
}
|
||||
return getRawPart(ctm, pkgPart, rel);
|
||||
}
|
||||
|
||||
public static org.docx4j.openpackaging.parts.Part getRawPart(ContentTypeManager ctm, Part pkgPart, Relationship rel) throws Docx4JException {
|
||||
org.docx4j.openpackaging.parts.Part part = null;
|
||||
try {
|
||||
Element el = null;
|
||||
try {
|
||||
String contentType = pkgPart.getContentType();
|
||||
log.debug("contentType: " + contentType);
|
||||
if (pkgPart.getXmlData() != null)
|
||||
el = pkgPart.getXmlData().getAny();
|
||||
part = ctm.newPartForContentType(contentType, pkgPart.getName(), rel);
|
||||
part.setContentType(new ContentType(contentType));
|
||||
ctm.addOverrideContentType(new URI(pkgPart.getName()), contentType);
|
||||
if (part instanceof org.docx4j.openpackaging.parts.ThemePart) {
|
||||
((JaxbXmlPart)part).setJAXBContext(Context.jcThemePart);
|
||||
((JaxbXmlPart)part).unmarshal(el);
|
||||
} else if (part instanceof org.docx4j.openpackaging.parts.DocPropsCorePart) {
|
||||
((JaxbXmlPart)part).setJAXBContext(Context.jcDocPropsCore);
|
||||
((JaxbXmlPart)part).unmarshal(el);
|
||||
} else if (part instanceof org.docx4j.openpackaging.parts.DocPropsCustomPart) {
|
||||
((JaxbXmlPart)part).setJAXBContext(Context.jcDocPropsCustom);
|
||||
((JaxbXmlPart)part).unmarshal(el);
|
||||
} else if (part instanceof org.docx4j.openpackaging.parts.DocPropsExtendedPart) {
|
||||
((JaxbXmlPart)part).setJAXBContext(Context.jcDocPropsExtended);
|
||||
((JaxbXmlPart)part).unmarshal(el);
|
||||
} else if (part instanceof org.docx4j.openpackaging.parts.CustomXmlDataStoragePropertiesPart) {
|
||||
((JaxbXmlPart)part).setJAXBContext(Context.jcCustomXmlProperties);
|
||||
((JaxbXmlPart)part).unmarshal(el);
|
||||
} else if (part instanceof org.docx4j.openpackaging.parts.digitalsignature.XmlSignaturePart) {
|
||||
((JaxbXmlPart)part).setJAXBContext(Context.jcXmlDSig);
|
||||
((JaxbXmlPart)part).unmarshal(el);
|
||||
} else if (part instanceof org.docx4j.openpackaging.parts.PresentationML.JaxbPmlPart) {
|
||||
((JaxbXmlPart)part).setJAXBContext(org.pptx4j.jaxb.Context.jcPML);
|
||||
((JaxbXmlPart)part).unmarshal(el);
|
||||
} else if (part instanceof JaxbXmlPart) {
|
||||
((JaxbXmlPart)part).setJAXBContext(Context.jc);
|
||||
((JaxbXmlPart)part).unmarshal(el);
|
||||
} else if (part instanceof BinaryPart) {
|
||||
log.debug("Detected BinaryPart " + part.getClass().getName());
|
||||
((BinaryPart)part).setBinaryData(pkgPart.getBinaryData());
|
||||
} else if (part instanceof CustomXmlDataStoragePart) {
|
||||
try {
|
||||
Unmarshaller u = Context.jc.createUnmarshaller();
|
||||
Object o = u.unmarshal(el);
|
||||
log.debug(o.getClass().getName());
|
||||
PartName name = part.getPartName();
|
||||
if (o instanceof CoverPageProperties) {
|
||||
part = new DocPropsCoverPagePart(name);
|
||||
((DocPropsCoverPagePart)part).setJaxbElement((CoverPageProperties)o);
|
||||
} else if (o instanceof Conditions) {
|
||||
part = new ConditionsPart(name);
|
||||
((ConditionsPart)part).setJaxbElement((Conditions)o);
|
||||
} else if (o instanceof Xpaths) {
|
||||
part = new XPathsPart(name);
|
||||
((XPathsPart)part).setJaxbElement((Xpaths)o);
|
||||
} else if (o instanceof Questionnaire) {
|
||||
part = new QuestionsPart(name);
|
||||
((QuestionsPart)part).setJaxbElement((Questionnaire)o);
|
||||
} else if (o instanceof Answers) {
|
||||
part = new StandardisedAnswersPart(name);
|
||||
((StandardisedAnswersPart)part).setJaxbElement((Answers)o);
|
||||
} else if (o instanceof Components) {
|
||||
part = new ComponentsPart(name);
|
||||
((ComponentsPart)part).setJaxbElement((Components)o);
|
||||
} else if (o instanceof JAXBElement && XmlUtils.unwrap(o) instanceof CTSources) {
|
||||
part = new BibliographyPart(name);
|
||||
((BibliographyPart)part).setJaxbElement((JAXBElement<CTSources>)o);
|
||||
} else {
|
||||
log.warn("No known part after all for CustomXmlPart " + o.getClass().getName());
|
||||
CustomXmlDataStorage data = Load.getCustomXmlDataStorageClass().factory();
|
||||
Document doc = XmlUtils.getNewDocumentBuilder().newDocument();
|
||||
Node copy = doc.importNode(el, true);
|
||||
try {
|
||||
copy.getAttributes().removeNamedItemNS("http://www.w3.org/2000/xmlns/", "xml");
|
||||
} catch (DOMException e) {}
|
||||
doc.appendChild(copy);
|
||||
data.setDocument(doc);
|
||||
((CustomXmlDataStoragePart)part).setData(data);
|
||||
}
|
||||
} catch (UnmarshalException ue) {
|
||||
CustomXmlDataStorage data = Load.getCustomXmlDataStorageClass().factory();
|
||||
Document doc = XmlUtils.getNewDocumentBuilder().newDocument();
|
||||
Node copy = doc.importNode(el, true);
|
||||
try {
|
||||
copy.getAttributes().removeNamedItemNS("http://www.w3.org/2000/xmlns/", "xml");
|
||||
} catch (DOMException e) {}
|
||||
doc.appendChild(copy);
|
||||
data.setDocument(doc);
|
||||
((CustomXmlDataStoragePart)part).setData(data);
|
||||
}
|
||||
} else if (part instanceof XmlPart) {
|
||||
Document doc = XmlUtils.getNewDocumentBuilder().newDocument();
|
||||
Node copy = doc.importNode(el, true);
|
||||
try {
|
||||
copy.getAttributes().removeNamedItemNS("http://www.w3.org/2000/xmlns/", "xml");
|
||||
} catch (DOMException e) {}
|
||||
doc.appendChild(copy);
|
||||
((XmlPart)part).setDocument(doc);
|
||||
} else {
|
||||
log.error("No suitable part found for: " + pkgPart.getName());
|
||||
part = null;
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
if (el != null) {
|
||||
log.error(e.getMessage());
|
||||
log.error(XmlUtils.w3CDomNodeToString(el));
|
||||
}
|
||||
throw e;
|
||||
} catch (PartUnrecognisedException e) {
|
||||
log.error("Part unrecognised: " + pkgPart.getName());
|
||||
part = new BinaryPart(new PartName(pkgPart.getName()));
|
||||
((BinaryPart)part).setBinaryData(pkgPart.getBinaryData());
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
throw new Docx4JException("Failed to getPart", ex);
|
||||
}
|
||||
return part;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String inputfilepath = "/home/dev/workspace/docx4j/sample-docs/pkg.pkg";
|
||||
FileInputStream fin = new FileInputStream(inputfilepath);
|
||||
JAXBContext jc = Context.jcXmlPackage;
|
||||
Unmarshaller u = jc.createUnmarshaller();
|
||||
u.setEventHandler(new JaxbValidationEventHandler());
|
||||
Object o = u.unmarshal(new StreamSource(fin));
|
||||
Package xmlPackage = (Package)((JAXBElement)o).getValue();
|
||||
FlatOpcXmlImporter inWorker = new FlatOpcXmlImporter(xmlPackage);
|
||||
WordprocessingMLPackage wordMLPackage = (WordprocessingMLPackage)inWorker.get();
|
||||
FlatOpcXmlCreator outWorker = new FlatOpcXmlCreator(wordMLPackage);
|
||||
Package result = outWorker.get();
|
||||
boolean suppressDeclaration = true;
|
||||
boolean prettyprint = true;
|
||||
log.debug(XmlUtils.marshaltoString(result, suppressDeclaration, prettyprint, Context.jcXmlPackage));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,232 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:transit="http://www.docx4java.org/word2003xml/to/wordprocessingml/2006"
|
||||
xmlns:aml="http://schemas.microsoft.com/aml/2001/core"
|
||||
xmlns:w03="http://schemas.microsoft.com/office/word/2003/wordml"
|
||||
xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint"
|
||||
xmlns:wsp="http://schemas.microsoft.com/office/word/2003/wordml/sp2"
|
||||
xmlns:sl="http://schemas.microsoft.com/schemaLibrary/2003/core"
|
||||
xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas"
|
||||
xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"
|
||||
xmlns:o="urn:schemas-microsoft-com:office:office"
|
||||
xmlns:v="urn:schemas-microsoft-com:vml"
|
||||
xmlns:w10="urn:schemas-microsoft-com:office:word"
|
||||
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
|
||||
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
|
||||
>
|
||||
|
||||
<!-- This stylesheet is the first phase of a proof of concept of converting Word 2003 XML,
|
||||
to ECMA 376.
|
||||
|
||||
It produces output matching:
|
||||
|
||||
<xsd:element name="transition03to06">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="w:fonts" />
|
||||
<xsd:element ref="w:numbering" />
|
||||
<xsd:element ref="w:styles" />
|
||||
<xsd:element ref="w:body" />
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
where wordDocument is in namespace http://www.docx4java.org/word2003xml/to/wordprocessingml/2006
|
||||
and its children are real http://schemas.openxmlformats.org/wordprocessingml/2006/main content.
|
||||
|
||||
-->
|
||||
|
||||
<xsl:output method="xml" indent="yes"/>
|
||||
|
||||
<xsl:template match="@* | node()">
|
||||
<xsl:copy>
|
||||
<xsl:apply-templates select="@* | node()"/>
|
||||
</xsl:copy>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="w03:wordDocument">
|
||||
<!-- Put this in the transit namespace and drop its attributes eg: w:macrosPresent="no" w:embeddedObjPresent="no" w:ocxPresent="no" xml:space="preserve" -->
|
||||
<xsl:element namespace="http://www.docx4java.org/word2003xml/to/wordprocessingml/2006" name="transition03to06">
|
||||
<xsl:apply-templates select="node()"/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
<!-- move descendents to modern namespace-->
|
||||
<xsl:template match="w03:*">
|
||||
<xsl:element namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" name="{local-name()}">
|
||||
<xsl:apply-templates select="@* | node()"/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="@*">
|
||||
<xsl:attribute namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" name="{local-name()}">
|
||||
<xsl:value-of select="."/>
|
||||
</xsl:attribute>
|
||||
</xsl:template>
|
||||
|
||||
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<!-- +++ ignoreSubtree ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<xsl:template match="w03:ignoreSubtree" />
|
||||
|
||||
|
||||
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<!-- +++ o:DocumentProperties +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<!-- TODO convert these-->
|
||||
<xsl:template match="o:DocumentProperties" />
|
||||
|
||||
|
||||
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<!-- +++ fonts ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<xsl:template match="w03:fonts">
|
||||
<xsl:element namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" name="fonts">
|
||||
<xsl:apply-templates select="@* | node()"/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="w03:panose-1">
|
||||
<xsl:element namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" name="panose">
|
||||
<xsl:apply-templates select="@* | node()"/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="@w03:usb-0" >
|
||||
<xsl:attribute namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" name="usb0">
|
||||
<xsl:value-of select="."/>
|
||||
</xsl:attribute>
|
||||
</xsl:template>
|
||||
<xsl:template match="@w03:usb-1" >
|
||||
<xsl:attribute namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" name="usb1">
|
||||
<xsl:value-of select="."/>
|
||||
</xsl:attribute>
|
||||
</xsl:template>
|
||||
<xsl:template match="@w03:usb-2" >
|
||||
<xsl:attribute namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" name="usb2">
|
||||
<xsl:value-of select="."/>
|
||||
</xsl:attribute>
|
||||
</xsl:template>
|
||||
<xsl:template match="@w03:usb-3" >
|
||||
<xsl:attribute namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" name="usb3">
|
||||
<xsl:value-of select="."/>
|
||||
</xsl:attribute>
|
||||
</xsl:template>
|
||||
<xsl:template match="@w03:csb-0" >
|
||||
<xsl:attribute namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" name="csb0">
|
||||
<xsl:value-of select="."/>
|
||||
</xsl:attribute>
|
||||
</xsl:template>
|
||||
<xsl:template match="@w03:csb-1" >
|
||||
<xsl:attribute namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" name="csb1">
|
||||
<xsl:value-of select="."/>
|
||||
</xsl:attribute>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<!-- +++ lists ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<xsl:template match="w03:lists">
|
||||
<xsl:element namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" name="numbering">
|
||||
<xsl:apply-templates select="@* | node()"/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
<xsl:template match="w03:defaultFonts" /> <!-- drop for now -->
|
||||
|
||||
<!-- listDef becomes abstractNum-->
|
||||
<xsl:template match="w03:listDef">
|
||||
<xsl:element namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" name="abstractNum">
|
||||
<xsl:apply-templates select="@* | node()"/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="@w03:listDefId" >
|
||||
<xsl:attribute namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" name="abstractNumId">
|
||||
<xsl:value-of select="."/>
|
||||
</xsl:attribute>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="w03:lsid">
|
||||
<xsl:element namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" name="nsid">
|
||||
<xsl:apply-templates select="@* | node()"/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="w03:plt">
|
||||
<xsl:element namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" name="multiLevelType">
|
||||
<xsl:apply-templates select="@* | node()"/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="@w03:tplc" />
|
||||
<xsl:template match="@w03:tentative" />
|
||||
<xsl:template match="@w03:hint" />
|
||||
|
||||
|
||||
<!-- list becomes num-->
|
||||
<xsl:template match="w03:list">
|
||||
<xsl:element namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" name="num">
|
||||
<xsl:apply-templates select="@* | node()"/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
<xsl:template match="@w03:ilfo" >
|
||||
<xsl:attribute namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" name="numId">
|
||||
<xsl:value-of select="."/>
|
||||
</xsl:attribute>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="w03:ilst">
|
||||
<xsl:element namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" name="abstractNumId">
|
||||
<xsl:apply-templates select="@* | node()"/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<!-- +++ styles +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<xsl:template match="w03:styles">
|
||||
<xsl:element namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" name="{local-name()}">
|
||||
<xsl:apply-templates select="@* | node()"/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
<xsl:template match="w03:versionOfBuiltInStylenames" />
|
||||
|
||||
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<!-- +++ shapeDefaults ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<xsl:template match="w03:shapeDefaults" />
|
||||
|
||||
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<!-- +++ docPr ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<xsl:template match="w03:docPr" />
|
||||
|
||||
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<!-- +++ body +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<xsl:template match="w03:body">
|
||||
<xsl:element namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" name="{local-name()}">
|
||||
<xsl:apply-templates select="@* | node()"/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
<!-- drop wx-->
|
||||
<xsl:template match="wx:*">
|
||||
<xsl:apply-templates select="node()"/>
|
||||
</xsl:template>
|
||||
|
||||
<!-- drop aml for now. TODO convert to WordML -->
|
||||
<xsl:template match="aml:*">
|
||||
<xsl:apply-templates select="node()"/>
|
||||
</xsl:template>
|
||||
<xsl:template match="w03:delText" />
|
||||
|
||||
<!-- drop image data for now. TODO come back and get this later.. -->
|
||||
<xsl:template match="w03:pict" />
|
||||
<xsl:template match="w03:binData" />
|
||||
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package org.docx4j.convert.in.word2003xml;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRegistry;
|
||||
|
||||
@XmlRegistry
|
||||
public class ObjectFactory {
|
||||
public Transition03To06 createTransition03To06() {
|
||||
return new Transition03To06();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
package org.docx4j.convert.in.word2003xml;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
import org.docx4j.wml.Body;
|
||||
import org.docx4j.wml.Fonts;
|
||||
import org.docx4j.wml.Numbering;
|
||||
import org.docx4j.wml.Styles;
|
||||
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "", propOrder = {"fonts", "numbering", "styles", "body"})
|
||||
@XmlRootElement(name = "transition03to06")
|
||||
public class Transition03To06 {
|
||||
@XmlElement(namespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", required = true)
|
||||
protected Fonts fonts;
|
||||
|
||||
@XmlElement(namespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", required = true)
|
||||
protected Numbering numbering;
|
||||
|
||||
@XmlElement(namespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", required = true)
|
||||
protected Styles styles;
|
||||
|
||||
@XmlElement(namespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", required = true)
|
||||
protected Body body;
|
||||
|
||||
public Fonts getFonts() {
|
||||
return this.fonts;
|
||||
}
|
||||
|
||||
public void setFonts(Fonts value) {
|
||||
this.fonts = value;
|
||||
}
|
||||
|
||||
public Numbering getNumbering() {
|
||||
return this.numbering;
|
||||
}
|
||||
|
||||
public void setNumbering(Numbering value) {
|
||||
this.numbering = value;
|
||||
}
|
||||
|
||||
public Styles getStyles() {
|
||||
return this.styles;
|
||||
}
|
||||
|
||||
public void setStyles(Styles value) {
|
||||
this.styles = value;
|
||||
}
|
||||
|
||||
public Body getBody() {
|
||||
return this.body;
|
||||
}
|
||||
|
||||
public void setBody(Body value) {
|
||||
this.body = value;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
package org.docx4j.convert.in.word2003xml;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.util.JAXBResult;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.Templates;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.openpackaging.exceptions.InvalidFormatException;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.FontTablePart;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.NumberingDefinitionsPart;
|
||||
import org.docx4j.utils.ResourceUtils;
|
||||
import org.docx4j.wml.Numbering;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Word2003XmlConverter {
|
||||
private static Logger log = LoggerFactory.getLogger(Word2003XmlConverter.class);
|
||||
|
||||
static Templates xslt;
|
||||
|
||||
private Transition03To06 transitionContainer;
|
||||
|
||||
static {
|
||||
try {
|
||||
Source xsltSource = new StreamSource(ResourceUtils.getResource("org/docx4j/convert/in/word2003xml/2003-import.xslt"));
|
||||
xslt = XmlUtils.getTransformerTemplate(xsltSource);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error("Couldn't setup 2003-import.xslt", (Throwable)e);
|
||||
} catch (TransformerConfigurationException e) {
|
||||
e.printStackTrace();
|
||||
log.error("Couldn't setup 2003-import.xslt", (Throwable)e);
|
||||
}
|
||||
}
|
||||
|
||||
public Word2003XmlConverter(Source source) throws JAXBException, Docx4JException {
|
||||
JAXBResult result = new JAXBResult(JAXBContext.newInstance("org.docx4j.convert.in.word2003xml"));
|
||||
XmlUtils.transform(source, xslt, null, (Result)result);
|
||||
this.transitionContainer = (Transition03To06)result.getResult();
|
||||
}
|
||||
|
||||
private WordprocessingMLPackage getWordprocessingMLPackage() {
|
||||
return getWordprocessingMLPackage(false);
|
||||
}
|
||||
|
||||
private WordprocessingMLPackage getWordprocessingMLPackage(boolean mainDocOnly) {
|
||||
WordprocessingMLPackage wordMLPackage = null;
|
||||
try {
|
||||
wordMLPackage = WordprocessingMLPackage.createPackage();
|
||||
} catch (InvalidFormatException e) {}
|
||||
MainDocumentPart mdp = wordMLPackage.getMainDocumentPart();
|
||||
mdp.getJaxbElement().setBody(this.transitionContainer.getBody());
|
||||
if (!mainDocOnly) {
|
||||
mdp.getStyleDefinitionsPart(true).setJaxbElement(this.transitionContainer.getStyles());
|
||||
try {
|
||||
NumberingDefinitionsPart ndp = new NumberingDefinitionsPart();
|
||||
ndp.setJaxbElement(this.transitionContainer.getNumbering());
|
||||
mdp.addTargetPart(ndp);
|
||||
for (Numbering.AbstractNum anum : ndp.getJaxbElement().getAbstractNum()) {
|
||||
if (anum.getMultiLevelType() == null)
|
||||
continue;
|
||||
String multiLevelType = anum.getMultiLevelType().getVal();
|
||||
multiLevelType = multiLevelType.substring(0, 1).toLowerCase() + multiLevelType.substring(1);
|
||||
anum.getMultiLevelType().setVal(multiLevelType);
|
||||
}
|
||||
} catch (InvalidFormatException e) {}
|
||||
try {
|
||||
FontTablePart fontsPart = new FontTablePart();
|
||||
fontsPart.setJaxbElement(this.transitionContainer.getFonts());
|
||||
mdp.addTargetPart(fontsPart);
|
||||
} catch (InvalidFormatException e) {}
|
||||
}
|
||||
return wordMLPackage;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException, JAXBException, Docx4JException {
|
||||
boolean save = true;
|
||||
File file = new File(System.getProperty("user.dir") + "/sample-docs/word/2003/word2003xml.xml");
|
||||
Source source = new StreamSource(FileUtils.openInputStream(file));
|
||||
Word2003XmlConverter conv = new Word2003XmlConverter(source);
|
||||
WordprocessingMLPackage wordMLPackage = conv.getWordprocessingMLPackage();
|
||||
if (save) {
|
||||
String filename = System.getProperty("user.dir") + "/OUT_FromWord2003XML.docx";
|
||||
wordMLPackage.save(new File(filename));
|
||||
System.out.println("Saved " + filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package org.docx4j.convert.in.word2003xml;
|
||||
|
||||
import javax.xml.bind.annotation.XmlNsForm;
|
||||
import javax.xml.bind.annotation.XmlSchema;
|
||||
|
||||
@XmlSchema(namespace = "http://www.docx4java.org/word2003xml/to/wordprocessingml/2006", elementFormDefault = XmlNsForm.QUALIFIED)
|
||||
interface package-info {}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package org.docx4j.convert.in.xhtml;
|
||||
|
||||
public enum FormattingOption {
|
||||
CLASS_TO_STYLE_ONLY, CLASS_PLUS_OTHER, IGNORE_CLASS;
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package org.docx4j.convert.in.xhtml;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import javax.xml.transform.Source;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
public interface XHTMLImporter {
|
||||
void setHyperlinkStyle(String paramString);
|
||||
|
||||
void setRunFormatting(FormattingOption paramFormattingOption);
|
||||
|
||||
void setParagraphFormatting(FormattingOption paramFormattingOption);
|
||||
|
||||
void setTableFormatting(FormattingOption paramFormattingOption);
|
||||
|
||||
List<Object> convert(File paramFile, String paramString) throws Docx4JException;
|
||||
|
||||
List<Object> convert(InputSource paramInputSource, String paramString) throws Docx4JException;
|
||||
|
||||
List<Object> convert(InputStream paramInputStream, String paramString) throws Docx4JException;
|
||||
|
||||
List<Object> convert(Node paramNode, String paramString) throws Docx4JException;
|
||||
|
||||
List<Object> convert(Reader paramReader, String paramString) throws Docx4JException;
|
||||
|
||||
List<Object> convert(Source paramSource, String paramString) throws Docx4JException;
|
||||
|
||||
List<Object> convert(URL paramURL) throws Docx4JException;
|
||||
|
||||
List<Object> convert(String paramString1, String paramString2) throws Docx4JException;
|
||||
|
||||
Map<String, Integer> getSequenceCounters();
|
||||
|
||||
void setSequenceCounters(Map<String, Integer> paramMap);
|
||||
|
||||
AtomicInteger getBookmarkIdLast();
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
package org.docx4j.convert.out;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import org.docx4j.model.images.ConversionImageHandler;
|
||||
import org.docx4j.openpackaging.packages.OpcPackage;
|
||||
|
||||
public abstract class AbstractConversionSettings {
|
||||
public static final String IMAGE_INCLUDE_UUID = "imageIncludeUUID";
|
||||
|
||||
public static final String IMAGE_DIR_PATH = "imageDirPath";
|
||||
|
||||
public static final String IMAGE_HANDLER = "imageHandler";
|
||||
|
||||
public static final String HYPERLINK_HANDLER = "hyperlinkHandler";
|
||||
|
||||
public static final String WML_PACKAGE = "wmlPackage";
|
||||
|
||||
public static final String CUSTOM_XSLT_TEMPLATES = "customXsltTemplates";
|
||||
|
||||
protected Map<String, Object> settings = new TreeMap<String, Object>();
|
||||
|
||||
protected Set<String> features = new TreeSet<String>();
|
||||
|
||||
public Map<String, Object> getSettings() {
|
||||
return this.settings;
|
||||
}
|
||||
|
||||
public Set<String> getFeatures() {
|
||||
return this.features;
|
||||
}
|
||||
|
||||
public void addFeatures(String[] featuresArray) {
|
||||
if (featuresArray != null && featuresArray.length > 0)
|
||||
for (int i = 0; i < featuresArray.length; i++)
|
||||
getFeatures().add(featuresArray[i]);
|
||||
}
|
||||
|
||||
public void setImageDirPath(String imageDirPath) {
|
||||
this.settings.put("imageDirPath", imageDirPath);
|
||||
}
|
||||
|
||||
public String getImageDirPath() {
|
||||
return (String)this.settings.get("imageDirPath");
|
||||
}
|
||||
|
||||
public void setImageIncludeUUID(boolean imageIncludeUUID) {
|
||||
this.settings.put("imageIncludeUUID", Boolean.valueOf(imageIncludeUUID));
|
||||
}
|
||||
|
||||
public boolean isImageIncludeUUID() {
|
||||
return this.settings.containsKey("imageIncludeUUID") ? (Boolean)this.settings.get("imageIncludeUUID") : true;
|
||||
}
|
||||
|
||||
public void setImageHandler(ConversionImageHandler imageHandler) {
|
||||
this.settings.put("imageHandler", imageHandler);
|
||||
}
|
||||
|
||||
public ConversionImageHandler getImageHandler() {
|
||||
return (ConversionImageHandler)this.settings.get("imageHandler");
|
||||
}
|
||||
|
||||
public void setHyperlinkHandler(ConversionHyperlinkHandler hyperlinkHandler) {
|
||||
this.settings.put("hyperlinkHandler", hyperlinkHandler);
|
||||
}
|
||||
|
||||
public ConversionHyperlinkHandler getHyperlinkHandler() {
|
||||
return (ConversionHyperlinkHandler)this.settings.get("hyperlinkHandler");
|
||||
}
|
||||
|
||||
public void setWmlPackage(OpcPackage wmlPackage) {
|
||||
this.settings.put("wmlPackage", wmlPackage);
|
||||
}
|
||||
|
||||
public OpcPackage getWmlPackage() {
|
||||
return (OpcPackage)this.settings.get("wmlPackage");
|
||||
}
|
||||
|
||||
public void setCustomXsltTemplates(Object templates) {
|
||||
this.settings.put("customXsltTemplates", templates);
|
||||
}
|
||||
|
||||
public Object getCustomXsltTemplates() {
|
||||
return this.settings.get("customXsltTemplates");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package org.docx4j.convert.out;
|
||||
|
||||
import java.util.Set;
|
||||
import org.docx4j.openpackaging.packages.OpcPackage;
|
||||
|
||||
public abstract class ConversionFeatures {
|
||||
public static final String PP_COMMON_DEEP_COPY = "pp.common.deepcopy";
|
||||
|
||||
public static final String PP_COMMON_MOVE_BOOKMARKS = "pp.common.movebookmarks";
|
||||
|
||||
public static final String PP_COMMON_MOVE_PAGEBREAK = "pp.common.movepagebreak";
|
||||
|
||||
public static final String PP_COMMON_CONTAINERIZATION = "pp.common.containerization";
|
||||
|
||||
public static final String PP_COMMON_COMBINE_FIELDS = "pp.common.combinefields";
|
||||
|
||||
public static final String PP_COMMON_PAGE_NUMBERING = "pp.common.pagenumbering";
|
||||
|
||||
public static final String PP_COMMON_DUMMY_PAGE_NUMBERING = "pp.common.dummypagenumbering";
|
||||
|
||||
public static final String PP_COMMON_CREATE_SECTIONS = "pp.common.createsections";
|
||||
|
||||
public static final String PP_COMMON_DUMMY_CREATE_SECTIONS = "pp.common.dummycreatesections";
|
||||
|
||||
public static final String PP_PDF_APACHEFOP_DISABLE_PAGEBREAK_FIRST_PARAGRAPH = "pp.apachefop.disablepagebreakfirstparagraph";
|
||||
|
||||
public static final String PP_PDF_APACHEFOP_DISABLE_PAGEBREAK_LIST_ITEM = "pp.apachefop.disablepagebreaklistitem";
|
||||
|
||||
public static final String PP_PDF_COVERPAGE_MOVE_SECTPR = "pp.common.coverpagemovesectpr";
|
||||
|
||||
public static final String PP_COMMON_TABLE_PARAGRAPH_STYLE_FIX = "pp.common.tbl-p-style-fix";
|
||||
|
||||
public static final String[] DEFAULT_PDF_FEATURES = new String[] { "pp.common.deepcopy", "pp.common.movebookmarks", "pp.common.movepagebreak", "pp.common.coverpagemovesectpr", "pp.common.containerization", "pp.common.combinefields", "pp.common.pagenumbering", "pp.common.createsections", "pp.apachefop.disablepagebreakfirstparagraph", "pp.common.tbl-p-style-fix" };
|
||||
|
||||
public static final String[] DEFAULT_HTML_FEATURES = new String[] { "pp.common.deepcopy", "pp.common.movebookmarks", "pp.common.movepagebreak", "pp.common.containerization", "pp.common.combinefields", "pp.common.dummypagenumbering", "pp.common.dummycreatesections", "pp.common.tbl-p-style-fix" };
|
||||
|
||||
protected static void checkParams(OpcPackage opcPackage, Set<String> features) {
|
||||
if (opcPackage == null)
|
||||
throw new IllegalArgumentException("The passed opcPackage is null.");
|
||||
if (features == null)
|
||||
throw new IllegalArgumentException("The set of the features is null.");
|
||||
if (features.contains("pp.common.pagenumbering"))
|
||||
features.add("pp.common.combinefields");
|
||||
if (!features.contains("pp.common.pagenumbering"))
|
||||
features.add("pp.common.dummypagenumbering");
|
||||
if (!features.contains("pp.common.createsections"))
|
||||
features.add("pp.common.dummycreatesections");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package org.docx4j.convert.out;
|
||||
|
||||
import org.docx4j.openpackaging.packages.OpcPackage;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
public interface ConversionHTMLScriptElementHandler {
|
||||
Element createScriptElement(OpcPackage paramOpcPackage, Document paramDocument, String paramString);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package org.docx4j.convert.out;
|
||||
|
||||
import org.docx4j.openpackaging.packages.OpcPackage;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
public interface ConversionHTMLStyleElementHandler {
|
||||
Element createStyleElement(OpcPackage paramOpcPackage, Document paramDocument, String paramString);
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package org.docx4j.convert.out;
|
||||
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.openpackaging.packages.OpcPackage;
|
||||
import org.docx4j.openpackaging.parts.Part;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
public interface ConversionHyperlinkHandler {
|
||||
void handleHyperlink(Model paramModel, OpcPackage paramOpcPackage, Part paramPart) throws Docx4JException;
|
||||
|
||||
public static interface Model {
|
||||
String getTarget();
|
||||
|
||||
void setTarget(String param1String);
|
||||
|
||||
boolean isExternal();
|
||||
|
||||
void setExternal(boolean param1Boolean);
|
||||
|
||||
String getAnchor();
|
||||
|
||||
void setAnchor(String param1String);
|
||||
|
||||
String getDocLocation();
|
||||
|
||||
void setDocLocation(String param1String);
|
||||
|
||||
String getRId();
|
||||
|
||||
void setRId(String param1String);
|
||||
|
||||
String getTgtFrame();
|
||||
|
||||
void setTgtFrame(String param1String);
|
||||
|
||||
String getTooltip();
|
||||
|
||||
void setTooltip(String param1String);
|
||||
|
||||
Node getContent();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package org.docx4j.convert.out;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
|
||||
public interface FORenderer {
|
||||
public static final String PLACEHOLDER_PREFIX = "${";
|
||||
|
||||
public static final String PLACEHOLDER_SUFFIX = "}";
|
||||
|
||||
void render(String paramString, FOSettings paramFOSettings, boolean paramBoolean, List<SectionPageInformation> paramList, OutputStream paramOutputStream) throws Docx4JException;
|
||||
|
||||
public static interface SectionPageInformation {
|
||||
String getDocumentPageCountID();
|
||||
|
||||
String getDocumentPageCountFoFormat();
|
||||
|
||||
String getSectionPageCountID();
|
||||
|
||||
String getSectionPageCountFoFormat();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package org.docx4j.convert.out;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class FOSettings extends AbstractConversionSettings {
|
||||
public static final String INTERNAL_FO_MIME = "application/xml-fo";
|
||||
|
||||
public static final String MIME_PDF = "application/pdf";
|
||||
|
||||
public static final String APACHEFOP_CONFIGURATION = "apacheFopConfiguration";
|
||||
|
||||
public static final String APACHEFOP_MIME = "apacheFopMime";
|
||||
|
||||
public static final String CUSTOM_FO_RENDERER = "customFoRenderer";
|
||||
|
||||
public static final String FO_DUMP_FILE = "foDumpFile";
|
||||
|
||||
public FOSettings() {
|
||||
addFeatures(ConversionFeatures.DEFAULT_PDF_FEATURES);
|
||||
}
|
||||
|
||||
public String getApacheFopConfiguration() {
|
||||
return (String)this.settings.get("apacheFopConfiguration");
|
||||
}
|
||||
|
||||
public void setApacheFopConfiguration(String apacheFopConfiguration) {
|
||||
this.settings.put("apacheFopConfiguration", apacheFopConfiguration);
|
||||
}
|
||||
|
||||
public String getApacheFopMime() {
|
||||
return (String)this.settings.get("apacheFopMime");
|
||||
}
|
||||
|
||||
public void setApacheFopMime(String apacheFopMime) {
|
||||
this.settings.put("apacheFopMime", apacheFopMime);
|
||||
}
|
||||
|
||||
public FORenderer getCustomFoRenderer() {
|
||||
return (FORenderer)this.settings.get("customFoRenderer");
|
||||
}
|
||||
|
||||
public void setCustomFoRenderer(FORenderer customFoRenderer) {
|
||||
this.settings.put("customFoRenderer", customFoRenderer);
|
||||
}
|
||||
|
||||
public File getFoDumpFile() {
|
||||
return (File)this.settings.get("foDumpFile");
|
||||
}
|
||||
|
||||
public void setFoDumpFile(File foFile) {
|
||||
this.settings.put("foDumpFile", foFile);
|
||||
}
|
||||
|
||||
private boolean layoutMasterSetCalculationInProgress = false;
|
||||
|
||||
public boolean lsLayoutMasterSetCalculationInProgress() {
|
||||
return this.layoutMasterSetCalculationInProgress;
|
||||
}
|
||||
|
||||
public void setLayoutMasterSetCalculationInProgress(boolean layoutMasterSetCalculationInProgress) {
|
||||
this.layoutMasterSetCalculationInProgress = layoutMasterSetCalculationInProgress;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
package org.docx4j.convert.out;
|
||||
|
||||
import org.docx4j.fonts.Mapper;
|
||||
|
||||
public class HTMLSettings extends AbstractConversionSettings {
|
||||
public static final String IMAGE_TARGET_URI = "imageTargetUri";
|
||||
|
||||
public static final String CONDITIONAL_COMMENTS = "conditionalComments";
|
||||
|
||||
public static final String FONT_FAMILY_STACK = "fontFamilyStack";
|
||||
|
||||
public static final String STYLE_ELEMENT_HANDLER = "styleElementHandler";
|
||||
|
||||
public static final String SCRIPT_ELEMENT_HANDLER = "scriptElementHandler";
|
||||
|
||||
public static final String USER_CSS = "userCSS";
|
||||
|
||||
public static final String USER_SCRIPT = "userScript";
|
||||
|
||||
public static final String USER_BODY_TOP = "userBodyTop";
|
||||
|
||||
public static final String USER_BODY_TAIL = "userBodyTail";
|
||||
|
||||
public HTMLSettings() {
|
||||
this.settings.put("conditionalComments", Boolean.FALSE);
|
||||
this.settings.put("fontFamilyStack", Boolean.FALSE);
|
||||
this.settings.put("userCSS", "");
|
||||
this.settings.put("userScript", "");
|
||||
this.settings.put("userBodyTop", "<!-- userBodyTop goes here -->");
|
||||
this.settings.put("userBodyTail", "<!-- userBodyTail goes here -->");
|
||||
addFeatures(ConversionFeatures.DEFAULT_HTML_FEATURES);
|
||||
}
|
||||
|
||||
public void setConditionalComments(Boolean conditionalComments) {
|
||||
this.settings.put("conditionalComments", conditionalComments);
|
||||
}
|
||||
|
||||
public void setFontFamilyStack(boolean val) {
|
||||
this.settings.put("fontFamilyStack", new Boolean(val));
|
||||
}
|
||||
|
||||
public void setFontMapper(Mapper fontMapper) {
|
||||
this.settings.put("fontMapper", fontMapper);
|
||||
}
|
||||
|
||||
public Mapper getFontMapper() {
|
||||
return (Mapper)this.settings.get("fontMapper");
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getUserCSS() {
|
||||
return (String)this.settings.get("userCSS");
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setUserCSS(String val) {
|
||||
this.settings.put("userCSS", val);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getUserScript() {
|
||||
return (String)this.settings.get("userScript");
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setUserScript(String val) {
|
||||
this.settings.put("userScript", val);
|
||||
}
|
||||
|
||||
public String getUserBodyTop() {
|
||||
return (String)this.settings.get("userBodyTop");
|
||||
}
|
||||
|
||||
public void setUserBodyTop(String val) {
|
||||
this.settings.put("userBodyTop", val);
|
||||
}
|
||||
|
||||
public String getUserBodyTail() {
|
||||
return (String)this.settings.get("userBodyTail");
|
||||
}
|
||||
|
||||
public void setUserBodyTail(String val) {
|
||||
this.settings.put("userBodyTail", val);
|
||||
}
|
||||
|
||||
public void setImageTargetUri(String imageTargetUri) {
|
||||
this.settings.put("imageTargetUri", imageTargetUri);
|
||||
}
|
||||
|
||||
public String getImageTargetUri() {
|
||||
return (String)this.settings.get("imageTargetUri");
|
||||
}
|
||||
|
||||
public void setStyleElementHandler(ConversionHTMLStyleElementHandler styleElementHandler) {
|
||||
this.settings.put("styleElementHandler", styleElementHandler);
|
||||
}
|
||||
|
||||
public ConversionHTMLStyleElementHandler getStyleElementHandler() {
|
||||
return (ConversionHTMLStyleElementHandler)this.settings.get("styleElementHandler");
|
||||
}
|
||||
|
||||
public void setScriptElementHandler(ConversionHTMLScriptElementHandler scriptElementHandler) {
|
||||
this.settings.put("scriptElementHandler", scriptElementHandler);
|
||||
}
|
||||
|
||||
public ConversionHTMLScriptElementHandler getScriptElementHandler() {
|
||||
return (ConversionHTMLScriptElementHandler)this.settings.get("scriptElementHandler");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package org.docx4j.convert.out;
|
||||
|
||||
import javax.xml.transform.Result;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
|
||||
public interface Output {
|
||||
void output(Result paramResult) throws Docx4JException;
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
package org.docx4j.convert.out.XSLFO;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import org.apache.avalon.framework.configuration.Configuration;
|
||||
import org.docx4j.Docx4J;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.convert.out.FORenderer;
|
||||
import org.docx4j.convert.out.FOSettings;
|
||||
import org.docx4j.convert.out.fo.renderers.FORendererApacheFOP;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
public class XSLFOExporterNonXSLT {
|
||||
private static Logger log = LoggerFactory.getLogger(XSLFOExporterNonXSLT.class);
|
||||
|
||||
protected static final int DEFAULT_OUTPUT_SIZE = 102400;
|
||||
|
||||
FOSettings foSettings = null;
|
||||
|
||||
public XSLFOExporterNonXSLT(WordprocessingMLPackage wmlPackage, FOSettings pdfSettings) {
|
||||
this.foSettings = pdfSettings;
|
||||
if (this.foSettings.getWmlPackage() == null && wmlPackage != null)
|
||||
this.foSettings.setWmlPackage(wmlPackage);
|
||||
}
|
||||
|
||||
public Document export() throws Docx4JException {
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream(102400);
|
||||
Document ret = null;
|
||||
this.foSettings.setApacheFopMime("application/xml-fo");
|
||||
try {
|
||||
Docx4J.toFO(this.foSettings, outStream, 2);
|
||||
ret = XmlUtils.getNewDocumentBuilder().parse(new ByteArrayInputStream(outStream.toByteArray()));
|
||||
} catch (Docx4JException e) {
|
||||
log.error("Exception exporting document: " + e.getMessage(), (Throwable)e);
|
||||
} catch (SAXException e) {
|
||||
log.error("Exception parsing document: " + e.getMessage(), (Throwable)e);
|
||||
} catch (IOException e) {
|
||||
log.error("Exception parsing document: " + e.getMessage(), (Throwable)e);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String inputfilepath = System.getProperty("user.dir") + "/sample-docs/word/sample-docxv2.docx";
|
||||
WordprocessingMLPackage wmlPackage = WordprocessingMLPackage.load(new File(inputfilepath));
|
||||
FOSettings pdfSettings = new FOSettings();
|
||||
pdfSettings.setWmlPackage(wmlPackage);
|
||||
XSLFOExporterNonXSLT withoutXSLT = new XSLFOExporterNonXSLT(wmlPackage, pdfSettings);
|
||||
long startTime = System.currentTimeMillis();
|
||||
Document xslfo = withoutXSLT.export();
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("done. elapsed time: " + Math.round((float)((endTime - startTime) / 1000L)));
|
||||
log.info(XmlUtils.w3CDomNodeToString(xslfo));
|
||||
String outputfilepath = inputfilepath + "K.pdf";
|
||||
OutputStream os = new FileOutputStream(outputfilepath);
|
||||
withoutXSLT.output(xslfo, os, null);
|
||||
System.out.println("Saved " + outputfilepath);
|
||||
}
|
||||
|
||||
public void output(Document xslfo, OutputStream os, Configuration fopConfigZZZ) throws Docx4JException {
|
||||
FORenderer renderer = FORendererApacheFOP.getInstance();
|
||||
String foDocument = XmlUtils.w3CDomNodeToString(xslfo);
|
||||
renderer.render(foDocument, this.foSettings, false, null, os);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
package org.docx4j.convert.out.common;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.docx4j.convert.out.AbstractConversionSettings;
|
||||
import org.docx4j.convert.out.ConversionHyperlinkHandler;
|
||||
import org.docx4j.convert.out.common.writer.AbstractMessageWriter;
|
||||
import org.docx4j.model.images.ConversionImageHandler;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.openpackaging.packages.OpcPackage;
|
||||
import org.docx4j.openpackaging.parts.Part;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.traversal.NodeIterator;
|
||||
|
||||
public abstract class AbstractConversionContext {
|
||||
private static final Logger log = LoggerFactory.getLogger(AbstractConversionContext.class);
|
||||
|
||||
public static final String CONVERSION_CONTEXT_ID = "conversionContext";
|
||||
|
||||
protected static final AbstractMessageWriter DUMMY_WRITER = new AbstractMessageWriter() {
|
||||
public DocumentFragment notImplemented(AbstractConversionContext context, NodeIterator nodes, String message) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public DocumentFragment message(AbstractConversionContext context, String message) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String getOutputSuffix() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String getOutputPrefix() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
protected static final ConversionHyperlinkHandler DUMMY_HYPERLINK_HANDLER = new ConversionHyperlinkHandler() {
|
||||
public void handleHyperlink(ConversionHyperlinkHandler.Model hyperlinkModel, OpcPackage opcPackage, Part currentPart) throws Docx4JException {}
|
||||
};
|
||||
|
||||
private Map<String, Object> xsltParameters = null;
|
||||
|
||||
private OpcPackage opcPackage = null;
|
||||
|
||||
private ConversionImageHandler imageHandler = null;
|
||||
|
||||
private ConversionHyperlinkHandler hyperlinkHandler = null;
|
||||
|
||||
private AbstractMessageWriter messageWriter = null;
|
||||
|
||||
private AbstractConversionSettings settings = null;
|
||||
|
||||
public AbstractConversionSettings getConversionSettings() {
|
||||
return this.settings;
|
||||
}
|
||||
|
||||
protected AbstractConversionContext(AbstractMessageWriter messageWriter, AbstractConversionSettings conversionSettings, OpcPackage localOpcPackage) {
|
||||
initializeSettings(conversionSettings, localOpcPackage);
|
||||
this.messageWriter = initializeMessageWriter(messageWriter);
|
||||
}
|
||||
|
||||
protected void initializeSettings(AbstractConversionSettings settings, OpcPackage localOpcPackage) {
|
||||
if (settings != null) {
|
||||
this.settings = settings;
|
||||
if (localOpcPackage == null && settings.getWmlPackage() == null)
|
||||
throw new IllegalArgumentException("The OpcPackage is missing in the settings.");
|
||||
this.imageHandler = initializeImageHandler(settings, settings.getImageHandler());
|
||||
this.hyperlinkHandler = initializeHyperlinkHandler(settings, settings.getHyperlinkHandler());
|
||||
this.opcPackage = initializeOpcPackage(settings, (localOpcPackage != null) ? localOpcPackage : settings.getWmlPackage());
|
||||
this.xsltParameters = initializeXsltParameters(settings, settings.getSettings());
|
||||
}
|
||||
}
|
||||
|
||||
protected ConversionImageHandler initializeImageHandler(AbstractConversionSettings settings, ConversionImageHandler handler) {
|
||||
return handler;
|
||||
}
|
||||
|
||||
protected ConversionHyperlinkHandler initializeHyperlinkHandler(AbstractConversionSettings settings, ConversionHyperlinkHandler handler) {
|
||||
return (handler != null) ? handler : DUMMY_HYPERLINK_HANDLER;
|
||||
}
|
||||
|
||||
protected OpcPackage initializeOpcPackage(AbstractConversionSettings settings, OpcPackage opcPackage) {
|
||||
return opcPackage;
|
||||
}
|
||||
|
||||
protected Map<String, Object> initializeXsltParameters(AbstractConversionSettings settings, Map<String, Object> settingParameters) {
|
||||
Map<String, Object> ret = new HashMap<String, Object>();
|
||||
if (settingParameters != null) {
|
||||
ret.putAll(settingParameters);
|
||||
ret.remove("imageHandler");
|
||||
ret.remove("wmlPackage");
|
||||
ret.remove("imageIncludeUUID");
|
||||
ret.remove("imageDirPath");
|
||||
}
|
||||
ret.put("conversionContext", this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected AbstractMessageWriter initializeMessageWriter(AbstractMessageWriter writer) {
|
||||
return (writer != null) ? writer : DUMMY_WRITER;
|
||||
}
|
||||
|
||||
protected OpcPackage getOpcPackage() {
|
||||
return this.opcPackage;
|
||||
}
|
||||
|
||||
public ConversionImageHandler getImageHandler() {
|
||||
return this.imageHandler;
|
||||
}
|
||||
|
||||
protected ConversionHyperlinkHandler getHyperlinkHandler() {
|
||||
return this.hyperlinkHandler;
|
||||
}
|
||||
|
||||
public void handleHyperlink(ConversionHyperlinkHandler.Model model) throws Docx4JException {
|
||||
getHyperlinkHandler().handleHyperlink(model, getOpcPackage(), null);
|
||||
}
|
||||
|
||||
public AbstractMessageWriter getMessageWriter() {
|
||||
return this.messageWriter;
|
||||
}
|
||||
|
||||
public Map<String, Object> getXsltParameters() {
|
||||
return this.xsltParameters;
|
||||
}
|
||||
|
||||
public Logger getLog() {
|
||||
return log;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
package org.docx4j.convert.out.common;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import org.docx4j.convert.out.AbstractConversionSettings;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.openpackaging.packages.OpcPackage;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class AbstractExporter<CS extends AbstractConversionSettings, CC extends AbstractConversionContext, PK extends OpcPackage> implements Exporter<CS> {
|
||||
protected static Logger LocalLog = LoggerFactory.getLogger(AbstractExporter.class);
|
||||
|
||||
public void export(CS conversionSettings, OutputStream outputStream) throws Docx4JException {
|
||||
PK preprocessedPackage = null;
|
||||
ConversionSectionWrappers sectionWrappers = null;
|
||||
CC conversionContext = null;
|
||||
OutputStream intermediateOutputStream = null;
|
||||
long startTime = System.currentTimeMillis();
|
||||
long currentTime = startTime;
|
||||
Logger log = LocalLog;
|
||||
try {
|
||||
log.debug("Start conversion");
|
||||
preprocessedPackage = preprocess(conversionSettings);
|
||||
if (preprocessedPackage instanceof WordprocessingMLPackage)
|
||||
log.debug("Results of preprocess: " + ((WordprocessingMLPackage)preprocessedPackage).getMainDocumentPart().getXML());
|
||||
currentTime = logDebugStep(log, "Preprocessing", currentTime);
|
||||
sectionWrappers = createWrappers(conversionSettings, preprocessedPackage);
|
||||
currentTime = logDebugStep(log, "Create section wrappers", currentTime);
|
||||
conversionContext = createContext(conversionSettings, preprocessedPackage, sectionWrappers);
|
||||
currentTime = logDebugStep(log, "Create conversion context", currentTime);
|
||||
intermediateOutputStream = createIntermediateOutputStream(outputStream);
|
||||
process(conversionSettings, conversionContext, intermediateOutputStream);
|
||||
currentTime = logDebugStep(log, "Processing", currentTime);
|
||||
postprocess(conversionSettings, conversionContext, intermediateOutputStream, outputStream);
|
||||
currentTime = logDebugStep(log, "Postprocessing", currentTime);
|
||||
logDebugStep(log, "Conversion done", startTime);
|
||||
} catch (IllegalArgumentException e) {
|
||||
if (e.getMessage().contains("Only non-null Positions with an index can be checked"))
|
||||
throw new Docx4JException("Exception exporting package; FOP https://issues.apache.org/bugzilla/show_bug.cgi?id=54094 .. try PP_APACHEFOP_DISABLE_PAGEBREAK_LIST_ITEM", e);
|
||||
throw new Docx4JException("Exception exporting package", e);
|
||||
} catch (Exception e) {
|
||||
log.error("Exception exporting package", (Throwable)e);
|
||||
throw new Docx4JException("Exception exporting package", e);
|
||||
} finally {
|
||||
try {
|
||||
outputStream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected long logDebugStep(Logger log, String stepLabel, long startTime) {
|
||||
long currentTime = 0L;
|
||||
if (log.isDebugEnabled()) {
|
||||
currentTime = System.currentTimeMillis();
|
||||
log.debug(stepLabel + ", " + Long.toString(currentTime - startTime) + "ms");
|
||||
}
|
||||
return currentTime;
|
||||
}
|
||||
|
||||
protected abstract PK preprocess(CS paramCS) throws Docx4JException;
|
||||
|
||||
protected abstract ConversionSectionWrappers createWrappers(CS paramCS, PK paramPK) throws Docx4JException;
|
||||
|
||||
protected abstract CC createContext(CS paramCS, PK paramPK, ConversionSectionWrappers paramConversionSectionWrappers);
|
||||
|
||||
protected OutputStream createIntermediateOutputStream(OutputStream outputStream) throws Docx4JException {
|
||||
return outputStream;
|
||||
}
|
||||
|
||||
protected abstract void process(CS paramCS, CC paramCC, OutputStream paramOutputStream) throws Docx4JException;
|
||||
|
||||
protected void postprocess(CS conversionSettings, AbstractConversionContext conversionContext, OutputStream intermediateOutputStream, OutputStream outputStream) throws Docx4JException {}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package org.docx4j.convert.out.common;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import org.docx4j.convert.out.AbstractConversionSettings;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
|
||||
public abstract class AbstractExporterDelegate<CS extends AbstractConversionSettings, CC extends AbstractWmlConversionContext> {
|
||||
public abstract void process(CS paramCS, CC paramCC, OutputStream paramOutputStream) throws Docx4JException;
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
package org.docx4j.convert.out.common;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import org.docx4j.TraversalUtil;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.convert.out.AbstractConversionSettings;
|
||||
import org.docx4j.events.EventFinished;
|
||||
import org.docx4j.events.StartEvent;
|
||||
import org.docx4j.events.WellKnownProcessSteps;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.openpackaging.parts.Part;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
public abstract class AbstractVisitorExporterDelegate<CS extends AbstractConversionSettings, CC extends AbstractWmlConversionContext> extends AbstractExporterDelegate<CS, CC> {
|
||||
protected AbstractVisitorExporterGeneratorFactory<CC> generatorFactory = null;
|
||||
|
||||
protected AbstractVisitorExporterDelegate(AbstractVisitorExporterGeneratorFactory<CC> generatorFactory) {
|
||||
this.generatorFactory = generatorFactory;
|
||||
}
|
||||
|
||||
public void process(CS conversionSettings, CC conversionContext, OutputStream outputStream) throws Docx4JException {
|
||||
StartEvent startEvent = new StartEvent(conversionSettings.getWmlPackage(), WellKnownProcessSteps.OUT_AbstractVisitorExporterDelegate);
|
||||
startEvent.publish();
|
||||
Document document = null;
|
||||
Element documentRoot = null;
|
||||
Element documentRootBody = null;
|
||||
Element sectionRoot = null;
|
||||
Element sectionRootBody = null;
|
||||
Element currentParent = null;
|
||||
Element flow = null;
|
||||
conversionContext.setCurrentPartMainDocument();
|
||||
document = XmlUtils.neww3cDomDocument();
|
||||
currentParent = documentRoot = createDocumentRoot(conversionContext, document);
|
||||
document.appendChild(documentRoot);
|
||||
appendDocumentHeader(conversionContext, document, documentRoot);
|
||||
documentRootBody = createDocumentBody(conversionContext, document, documentRoot);
|
||||
if (documentRootBody != null) {
|
||||
currentParent.appendChild(documentRootBody);
|
||||
currentParent = documentRootBody;
|
||||
}
|
||||
List<ConversionSectionWrapper> sectionWrappers = conversionContext.getSections().getList();
|
||||
for (int secindex = 0; secindex < sectionWrappers.size(); secindex++) {
|
||||
ConversionSectionWrapper sectionWrapper = sectionWrappers.get(secindex);
|
||||
conversionContext.getSections().next();
|
||||
sectionRoot = createSectionRoot(conversionContext, document, sectionWrapper, currentParent);
|
||||
if (sectionRoot != null) {
|
||||
currentParent.appendChild(sectionRoot);
|
||||
currentParent = sectionRoot;
|
||||
}
|
||||
appendSectionHeader(conversionContext, document, sectionWrapper, currentParent);
|
||||
sectionRootBody = createSectionBody(conversionContext, document, sectionWrapper, currentParent);
|
||||
if (sectionRootBody != null) {
|
||||
currentParent.appendChild(sectionRootBody);
|
||||
currentParent = sectionRootBody;
|
||||
}
|
||||
generateBodyContent(conversionContext, document, sectionWrapper.getContent(), currentParent);
|
||||
currentParent = sectionRoot;
|
||||
if (currentParent == null) {
|
||||
currentParent = documentRootBody;
|
||||
if (currentParent == null)
|
||||
currentParent = documentRoot;
|
||||
}
|
||||
appendSectionFooter(conversionContext, document, sectionWrapper, currentParent);
|
||||
currentParent = documentRootBody;
|
||||
if (currentParent == null)
|
||||
currentParent = documentRoot;
|
||||
}
|
||||
appendDocumentFooter(conversionContext, document, documentRoot);
|
||||
writeDocument(conversionContext, document, outputStream);
|
||||
new EventFinished(startEvent).publish();
|
||||
}
|
||||
|
||||
protected abstract Element createDocumentRoot(CC paramCC, Document paramDocument) throws Docx4JException;
|
||||
|
||||
protected void appendDocumentHeader(CC conversionContext, Document document, Element documentRoot) throws Docx4JException {}
|
||||
|
||||
protected Element createDocumentBody(CC conversionContext, Document document, Element documentRoot) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Element createSectionRoot(CC conversionContext, Document document, ConversionSectionWrapper sectionWrapper, Element currentParent) throws Docx4JException {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void appendSectionHeader(CC conversionContext, Document document, ConversionSectionWrapper sectionWrapper, Element currentParent) throws Docx4JException {}
|
||||
|
||||
protected Element createSectionBody(CC conversionContext, Document document, ConversionSectionWrapper sectionWrapper, Element currentParent) throws Docx4JException {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void appendPartContent(CC conversionContext, Document document, Part part, List<Object> content, Element currentParent) throws Docx4JException {
|
||||
Part previousPart = conversionContext.getCurrentPart();
|
||||
conversionContext.setCurrentPart(part);
|
||||
generateBodyContent(conversionContext, document, content, currentParent);
|
||||
conversionContext.setCurrentPart(previousPart);
|
||||
}
|
||||
|
||||
protected void generateBodyContent(CC conversionContext, Document document, List<Object> content, Element currentParent) throws Docx4JException {
|
||||
AbstractVisitorExporterGenerator<CC> generator = this.generatorFactory.createInstance(conversionContext, document, currentParent);
|
||||
new TraversalUtil(content, generator);
|
||||
}
|
||||
|
||||
protected void appendSectionFooter(CC conversionContext, Document document, ConversionSectionWrapper sectionWrapper, Element currentParent) throws Docx4JException {}
|
||||
|
||||
protected void appendDocumentFooter(CC conversionContext, Document document, Element documentRoot) throws Docx4JException {}
|
||||
|
||||
protected void writeDocument(CC conversionContext, Document document, OutputStream outputStream) throws Docx4JException {
|
||||
Transformer serializer = null;
|
||||
try {
|
||||
serializer = XmlUtils.getTransformerFactory().newTransformer();
|
||||
serializer.setOutputProperty("omit-xml-declaration", "yes");
|
||||
serializer.setOutputProperty("method", "xml");
|
||||
serializer.transform(new DOMSource(document), new StreamResult(outputStream));
|
||||
} catch (Exception e) {
|
||||
throw new Docx4JException("Exception writing Document to OutputStream: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static interface AbstractVisitorExporterGeneratorFactory<CC extends AbstractWmlConversionContext> {
|
||||
AbstractVisitorExporterGenerator<CC> createInstance(CC param1CC, Document param1Document, Node param1Node);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,259 @@
|
|||
package org.docx4j.convert.out.common;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import org.docx4j.TraversalUtil;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.vml.CTShape;
|
||||
import org.docx4j.vml.CTTextbox;
|
||||
import org.docx4j.vml.wordprocessingDrawing.CTWrap;
|
||||
import org.docx4j.wml.Br;
|
||||
import org.docx4j.wml.ContentAccessor;
|
||||
import org.docx4j.wml.FldChar;
|
||||
import org.docx4j.wml.P;
|
||||
import org.docx4j.wml.PPr;
|
||||
import org.docx4j.wml.Pict;
|
||||
import org.docx4j.wml.R;
|
||||
import org.docx4j.wml.RPr;
|
||||
import org.docx4j.wml.Text;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.DOMException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
public abstract class AbstractVisitorExporterGenerator<CC extends AbstractWmlConversionContext> extends TraversalUtil.CallbackImpl {
|
||||
private static Logger log = LoggerFactory.getLogger(AbstractVisitorExporterGenerator.class);
|
||||
|
||||
protected static final String TAB_DUMMY = " ";
|
||||
|
||||
protected static final int NODE_BLOCK = 1;
|
||||
|
||||
protected static final int NODE_INLINE = 2;
|
||||
|
||||
protected static final int IMAGE_E10 = 1;
|
||||
|
||||
protected static final int IMAGE_E20 = 2;
|
||||
|
||||
protected CC conversionContext = null;
|
||||
|
||||
protected Document document = null;
|
||||
|
||||
protected Node parentNode = null;
|
||||
|
||||
protected Element currentP = null;
|
||||
|
||||
protected Element currentSpan = null;
|
||||
|
||||
protected LinkedList<Element> tr = new LinkedList<Element>();
|
||||
|
||||
protected LinkedList<Element> tc = new LinkedList<Element>();
|
||||
|
||||
protected PPr pPr = null;
|
||||
|
||||
protected RPr rPr = null;
|
||||
|
||||
protected Object anchorOrInline;
|
||||
|
||||
protected AbstractVisitorExporterGenerator(CC conversionContext, Document document, Node parentNode) {
|
||||
this.conversionContext = conversionContext;
|
||||
this.document = document;
|
||||
this.parentNode = parentNode;
|
||||
}
|
||||
|
||||
public boolean shouldTraverse(Object o) {
|
||||
if (o instanceof org.docx4j.wml.Tbl || o instanceof P.Hyperlink || o instanceof org.docx4j.wml.CTSimpleField || o instanceof CTTextbox || o instanceof FldChar)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected Node getCurrentParent() {
|
||||
return (this.currentSpan != null) ? this.currentSpan : ((this.currentP != null) ? this.currentP : this.parentNode);
|
||||
}
|
||||
|
||||
protected void convertToNode(CC conversionContext, Object unmarshalledNode, String modelId, Document document, Node parentNode) throws DOMException {
|
||||
log.debug(modelId);
|
||||
DocumentFragment childResults = null;
|
||||
if (unmarshalledNode instanceof ContentAccessor) {
|
||||
childResults = document.createDocumentFragment();
|
||||
AbstractVisitorExporterGenerator<CC> generator = getFactory().createInstance(conversionContext, document, childResults);
|
||||
new TraversalUtil(((ContentAccessor)unmarshalledNode).getContent(), generator);
|
||||
} else if (unmarshalledNode instanceof Pict) {
|
||||
CTTextbox textBox = getTextBox((Pict)unmarshalledNode);
|
||||
if (textBox != null) {
|
||||
childResults = document.createDocumentFragment();
|
||||
AbstractVisitorExporterGenerator<CC> generator = getFactory().createInstance(conversionContext, document, childResults);
|
||||
new TraversalUtil(textBox.getTxbxContent().getContent(), generator);
|
||||
}
|
||||
}
|
||||
Node resultNode = conversionContext.getWriterRegistry().toNode(conversionContext, unmarshalledNode, modelId, childResults, document);
|
||||
if (resultNode != null) {
|
||||
log.debug("Appending " + XmlUtils.w3CDomNodeToString(resultNode));
|
||||
parentNode.appendChild(resultNode);
|
||||
}
|
||||
}
|
||||
|
||||
protected void rtlAwareAppendChildToCurrentP(Element child) {
|
||||
this.parentNode.appendChild(child);
|
||||
}
|
||||
|
||||
public void walkJAXBElements(Object o) {
|
||||
Node existingParentNode = this.parentNode;
|
||||
if (o instanceof org.docx4j.wml.Tr) {
|
||||
this.tr.push(this.document.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "tr"));
|
||||
this.parentNode.appendChild(this.tr.peek());
|
||||
} else if (o instanceof org.docx4j.wml.Tc) {
|
||||
this.tc.push(this.document.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "tc"));
|
||||
this.tr.peek().appendChild(this.tc.peek());
|
||||
this.parentNode = this.tc.peek();
|
||||
}
|
||||
super.walkJAXBElements(o);
|
||||
if (o instanceof org.docx4j.wml.Tr) {
|
||||
this.tr.pop();
|
||||
} else if (o instanceof org.docx4j.wml.Tc) {
|
||||
this.tc.pop();
|
||||
this.parentNode = existingParentNode;
|
||||
}
|
||||
}
|
||||
|
||||
public List<Object> apply(Object o) {
|
||||
if (o instanceof P) {
|
||||
this.currentP = createNode(this.document, 1);
|
||||
this.currentSpan = null;
|
||||
if (this.tc.peek() != null) {
|
||||
this.tc.peek().appendChild(this.currentP);
|
||||
} else {
|
||||
this.parentNode.appendChild(this.currentP);
|
||||
}
|
||||
this.pPr = ((P)o).getPPr();
|
||||
this.currentP = handlePPr(this.conversionContext, this.pPr, false, this.currentP);
|
||||
} else if (o instanceof R) {
|
||||
if (!this.conversionContext.isInComplexFieldDefinition()) {
|
||||
Element spanEl = createNode(this.document, 2);
|
||||
this.currentSpan = spanEl;
|
||||
this.rPr = ((R)o).getRPr();
|
||||
if (this.rPr != null)
|
||||
handleRPr(this.conversionContext, this.pPr, this.rPr, this.currentSpan);
|
||||
if (this.currentP == null) {
|
||||
this.parentNode.appendChild(spanEl);
|
||||
} else {
|
||||
rtlAwareAppendChildToCurrentP(spanEl);
|
||||
}
|
||||
}
|
||||
} else if (o instanceof FldChar) {
|
||||
this.conversionContext.updateComplexFieldDefinition(((FldChar)o).getFldCharType());
|
||||
} else if (o instanceof Text) {
|
||||
if (!this.conversionContext.isInComplexFieldDefinition()) {
|
||||
if (this.currentSpan == null) {
|
||||
log.error("null currentSpan! " + ((Text)o).getValue());
|
||||
Element spanEl = createNode(this.document, 2);
|
||||
if (this.currentP == null) {
|
||||
this.parentNode.appendChild(spanEl);
|
||||
} else {
|
||||
this.currentP.appendChild(spanEl);
|
||||
}
|
||||
this.currentSpan = spanEl;
|
||||
}
|
||||
log.debug(((Text)o).getValue());
|
||||
DocumentFragment df = (DocumentFragment)this.conversionContext.getRunFontSelector().fontSelector(this.pPr, this.rPr, (Text)o);
|
||||
XmlUtils.treeCopy(df, this.currentSpan);
|
||||
}
|
||||
} else if (o instanceof R.Tab) {
|
||||
convertTabToNode(this.conversionContext, this.document);
|
||||
} else if (o instanceof org.docx4j.wml.CTSimpleField) {
|
||||
convertToNode(this.conversionContext, o, "w:fldSimple", this.document, getCurrentParent());
|
||||
} else if (o instanceof P.Hyperlink) {
|
||||
convertToNode(this.conversionContext, o, "w:hyperlink", this.document, getCurrentParent());
|
||||
} else if (o instanceof org.docx4j.wml.CTBookmark) {
|
||||
convertToNode(this.conversionContext, o, "w:bookmarkStart", this.document, getCurrentParent());
|
||||
} else if (o instanceof org.docx4j.wml.Tbl) {
|
||||
convertToNode(this.conversionContext, o, "w:tbl", this.document, (this.currentP != null) ? this.currentP : this.parentNode);
|
||||
this.currentP = null;
|
||||
this.currentSpan = null;
|
||||
} else if (!(o instanceof org.docx4j.wml.Tr)) {
|
||||
if (!(o instanceof org.docx4j.wml.Tc))
|
||||
if (o instanceof org.docx4j.dml.wordprocessingDrawing.Inline || o instanceof org.docx4j.dml.wordprocessingDrawing.Anchor) {
|
||||
this.anchorOrInline = o;
|
||||
} else if (o instanceof org.docx4j.dml.CTBlip) {
|
||||
DocumentFragment foreignFragment = createImage(2, this.conversionContext, this.anchorOrInline);
|
||||
this.anchorOrInline = null;
|
||||
this.currentP.appendChild(this.document.importNode(foreignFragment, true));
|
||||
} else if (o instanceof Pict) {
|
||||
CTTextbox textBox = getTextBox((Pict)o);
|
||||
if (textBox == null) {
|
||||
DocumentFragment foreignFragment = createImage(1, this.conversionContext, o);
|
||||
this.currentP.appendChild(this.document.importNode(foreignFragment, true));
|
||||
} else {
|
||||
convertToNode(this.conversionContext, o, "w:pict", this.document, getCurrentParent());
|
||||
}
|
||||
} else if (o instanceof Br) {
|
||||
handleBr((Br)o);
|
||||
} else if (o instanceof R.Sym) {
|
||||
convertToNode(this.conversionContext, o, "w:sym", this.document, getCurrentParent());
|
||||
} else if (!(o instanceof org.docx4j.wml.ProofErr) && !(o instanceof R.LastRenderedPageBreak) && !(o instanceof org.docx4j.wml.CTMarkupRange)) {
|
||||
log.warn("Need to handle " + o.getClass().getName());
|
||||
log.debug(XmlUtils.marshaltoString(o));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected abstract void handleBr(Br paramBr);
|
||||
|
||||
protected int getPos(List list, Object wanted) {
|
||||
int index = 0;
|
||||
for (Object o : (Iterable<Object>)list) {
|
||||
if (o == wanted)
|
||||
return index;
|
||||
index++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected void convertTabToNode(CC conversionContext, Document document) throws DOMException {
|
||||
if (!conversionContext.isInComplexFieldDefinition())
|
||||
getCurrentParent().appendChild(document.createTextNode(" "));
|
||||
}
|
||||
|
||||
private CTTextbox getTextBox(Pict pict) {
|
||||
CTShape shape = null;
|
||||
for (Object o2 : (Iterable<Object>)pict.getAnyAndAny()) {
|
||||
o2 = XmlUtils.unwrap(o2);
|
||||
if (o2 instanceof CTShape) {
|
||||
shape = (CTShape)o2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (shape == null) {
|
||||
log.warn("no shape in pict ");
|
||||
return null;
|
||||
}
|
||||
CTTextbox textBox = null;
|
||||
CTWrap w10Wrap = null;
|
||||
for (JAXBElement<?> o2 : shape.getPathOrFormulasOrHandles()) {
|
||||
o2 = (JAXBElement<?>)XmlUtils.unwrap(o2);
|
||||
if (o2 instanceof CTTextbox)
|
||||
textBox = (CTTextbox)o2;
|
||||
if (o2 instanceof CTWrap)
|
||||
w10Wrap = (CTWrap)o2;
|
||||
}
|
||||
return textBox;
|
||||
}
|
||||
|
||||
protected abstract Element handlePPr(CC paramCC, PPr paramPPr, boolean paramBoolean, Element paramElement);
|
||||
|
||||
protected abstract void handleRPr(CC paramCC, PPr paramPPr, RPr paramRPr, Element paramElement);
|
||||
|
||||
protected abstract AbstractVisitorExporterDelegate.AbstractVisitorExporterGeneratorFactory<CC> getFactory();
|
||||
|
||||
protected abstract DocumentFragment createImage(int paramInt, CC paramCC, Object paramObject);
|
||||
|
||||
protected abstract Element createNode(Document paramDocument, int paramInt);
|
||||
|
||||
protected Logger getLog() {
|
||||
return log;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
package org.docx4j.convert.out.common;
|
||||
|
||||
import java.util.Map;
|
||||
import org.docx4j.convert.out.AbstractConversionSettings;
|
||||
import org.docx4j.convert.out.ConversionHyperlinkHandler;
|
||||
import org.docx4j.convert.out.common.writer.AbstractMessageWriter;
|
||||
import org.docx4j.fonts.RunFontSelector;
|
||||
import org.docx4j.model.PropertyResolver;
|
||||
import org.docx4j.model.styles.StyleTree;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.openpackaging.packages.OpcPackage;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.openpackaging.parts.Part;
|
||||
import org.docx4j.wml.STFldCharType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class AbstractWmlConversionContext extends AbstractConversionContext {
|
||||
private static Logger log = LoggerFactory.getLogger(AbstractWmlConversionContext.class);
|
||||
|
||||
private Map<String, Writer.TransformState> transformStates = null;
|
||||
|
||||
private AbstractWriterRegistry writerRegistry = null;
|
||||
|
||||
protected Part currentPart = null;
|
||||
|
||||
protected int complexFieldDefinitionLevel = 0;
|
||||
|
||||
protected int footnoteNumberCounter = 0;
|
||||
|
||||
protected int endnoteNumberCounter = 0;
|
||||
|
||||
protected ConversionSectionWrappers conversionSectionWrappers = null;
|
||||
|
||||
protected StyleTree styleTree = null;
|
||||
|
||||
private RunFontSelector runFontSelector = null;
|
||||
|
||||
protected AbstractWmlConversionContext(AbstractWriterRegistry writerRegistry, AbstractMessageWriter messageWriter, AbstractConversionSettings conversionSettings, WordprocessingMLPackage wmlPackage, ConversionSectionWrappers conversionSectionWrappers, RunFontSelector runFontSelector) {
|
||||
super(messageWriter, conversionSettings, wmlPackage);
|
||||
this.writerRegistry = initializeWriterRegistry(writerRegistry);
|
||||
this.transformStates = initializeTransformStates();
|
||||
this.conversionSectionWrappers = conversionSectionWrappers;
|
||||
this.styleTree = initializeStyleTree();
|
||||
this.runFontSelector = runFontSelector;
|
||||
}
|
||||
|
||||
protected OpcPackage initializeOpcPackage(AbstractConversionSettings conversionSettings, OpcPackage opcPackage) {
|
||||
OpcPackage ret = super.initializeOpcPackage(conversionSettings, opcPackage);
|
||||
if (!(ret instanceof WordprocessingMLPackage))
|
||||
throw new IllegalArgumentException("The opcPackage isn't a WordprocessingMLPackage, it is a " + ret.getClass().getName());
|
||||
resolveLinkedAbstractNum((WordprocessingMLPackage)ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected AbstractWriterRegistry initializeWriterRegistry(AbstractWriterRegistry registry) {
|
||||
return registry;
|
||||
}
|
||||
|
||||
protected Map<String, Writer.TransformState> initializeTransformStates() {
|
||||
return getWriterRegistry().createTransformStates();
|
||||
}
|
||||
|
||||
protected void resolveLinkedAbstractNum(WordprocessingMLPackage wmlPkg) {
|
||||
if (wmlPkg.getMainDocumentPart().getStyleDefinitionsPart(false) != null && wmlPkg.getMainDocumentPart().getNumberingDefinitionsPart() != null)
|
||||
wmlPkg.getMainDocumentPart().getNumberingDefinitionsPart().resolveLinkedAbstractNum(wmlPkg.getMainDocumentPart().getStyleDefinitionsPart(false));
|
||||
}
|
||||
|
||||
protected StyleTree initializeStyleTree() {
|
||||
return getWmlPackage().getMainDocumentPart().getStyleTree();
|
||||
}
|
||||
|
||||
public Writer.TransformState getTransformState(String name) {
|
||||
return (this.transformStates != null) ? this.transformStates.get(name) : null;
|
||||
}
|
||||
|
||||
public WordprocessingMLPackage getWmlPackage() {
|
||||
return (WordprocessingMLPackage)getOpcPackage();
|
||||
}
|
||||
|
||||
public AbstractWriterRegistry getWriterRegistry() {
|
||||
return this.writerRegistry;
|
||||
}
|
||||
|
||||
public PropertyResolver getPropertyResolver() {
|
||||
return getWmlPackage().getMainDocumentPart().getPropertyResolver();
|
||||
}
|
||||
|
||||
public int getNextEndnoteNumber() {
|
||||
return this.endnoteNumberCounter++;
|
||||
}
|
||||
|
||||
public int getNextFootnoteNumber() {
|
||||
return this.footnoteNumberCounter++;
|
||||
}
|
||||
|
||||
public void setCurrentPart(Part currentPart) {
|
||||
this.currentPart = currentPart;
|
||||
}
|
||||
|
||||
public Part getCurrentPart() {
|
||||
return this.currentPart;
|
||||
}
|
||||
|
||||
public void setCurrentPartMainDocument() {
|
||||
setCurrentPart(getWmlPackage().getMainDocumentPart());
|
||||
}
|
||||
|
||||
public ConversionSectionWrappers getSections() {
|
||||
return this.conversionSectionWrappers;
|
||||
}
|
||||
|
||||
public StyleTree getStyleTree() {
|
||||
return this.styleTree;
|
||||
}
|
||||
|
||||
public RunFontSelector getRunFontSelector() {
|
||||
return this.runFontSelector;
|
||||
}
|
||||
|
||||
public void handleHyperlink(ConversionHyperlinkHandler.Model model) throws Docx4JException {
|
||||
getHyperlinkHandler().handleHyperlink(model, getOpcPackage(), getCurrentPart());
|
||||
}
|
||||
|
||||
public void updateComplexFieldDefinition(STFldCharType fieldCharType) {
|
||||
if (fieldCharType == STFldCharType.BEGIN) {
|
||||
this.complexFieldDefinitionLevel++;
|
||||
} else if (fieldCharType == STFldCharType.SEPARATE) {
|
||||
if (this.complexFieldDefinitionLevel == 1)
|
||||
this.complexFieldDefinitionLevel--;
|
||||
} else if (fieldCharType == STFldCharType.END &&
|
||||
this.complexFieldDefinitionLevel > 0) {
|
||||
this.complexFieldDefinitionLevel--;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isInComplexFieldDefinition() {
|
||||
return (this.complexFieldDefinitionLevel > 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package org.docx4j.convert.out.common;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import org.docx4j.convert.out.AbstractConversionSettings;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.openpackaging.packages.OpcPackage;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
|
||||
public abstract class AbstractWmlExporter<CS extends AbstractConversionSettings, CC extends AbstractWmlConversionContext> extends AbstractExporter<CS, CC, WordprocessingMLPackage> {
|
||||
protected AbstractExporterDelegate<CS, CC> exporterDelegate = null;
|
||||
|
||||
protected AbstractWmlExporter(AbstractExporterDelegate<CS, CC> exporterDelegate) {
|
||||
this.exporterDelegate = exporterDelegate;
|
||||
}
|
||||
|
||||
protected WordprocessingMLPackage preprocess(CS conversionSettings) throws Docx4JException {
|
||||
WordprocessingMLPackage wmlPackage = null;
|
||||
try {
|
||||
wmlPackage = (WordprocessingMLPackage)conversionSettings.getWmlPackage();
|
||||
} catch (ClassCastException cce) {
|
||||
throw new Docx4JException("Invalid document package in the settings, it isn't a WordprocessingMLPackage");
|
||||
}
|
||||
if (wmlPackage == null)
|
||||
throw new Docx4JException("Missing WordprocessingMLPackage in the conversion settings");
|
||||
return Preprocess.process(wmlPackage, conversionSettings.getFeatures());
|
||||
}
|
||||
|
||||
protected ConversionSectionWrappers createWrappers(CS conversionSettings, WordprocessingMLPackage preprocessedPackage) throws Docx4JException {
|
||||
ConversionSectionWrappers ret = null;
|
||||
ret = CreateWrappers.process(preprocessedPackage, conversionSettings.getFeatures());
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected void process(CS conversionSettings, CC conversionContext, OutputStream outputStream) throws Docx4JException {
|
||||
this.exporterDelegate.process(conversionSettings, conversionContext, outputStream);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
package org.docx4j.convert.out.common;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
public abstract class AbstractWriterRegistry {
|
||||
private static final Logger log = LoggerFactory.getLogger(AbstractWriterRegistry.class);
|
||||
|
||||
private Map<String, Writer> writerInstances = new HashMap<String, Writer>();
|
||||
|
||||
public AbstractWriterRegistry() {
|
||||
registerDefaultWriterInstances();
|
||||
}
|
||||
|
||||
protected abstract void registerDefaultWriterInstances();
|
||||
|
||||
public void registerWriter(Writer converter) {
|
||||
this.writerInstances.put(converter.getID(), converter);
|
||||
}
|
||||
|
||||
public Map<String, Writer.TransformState> createTransformStates() {
|
||||
Map<String, Writer.TransformState> ret = new HashMap<String, Writer.TransformState>();
|
||||
Writer.TransformState state = null;
|
||||
for (Map.Entry<String, Writer> item : this.writerInstances.entrySet()) {
|
||||
state = item.getValue().createTransformState();
|
||||
if (state != null)
|
||||
ret.put(item.getKey(), state);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Node toNode(AbstractWmlConversionContext context, Node node, NodeList childResults) {
|
||||
Object unmarshalledNode = null;
|
||||
Document doc = XmlUtils.neww3cDomDocument();
|
||||
Node content = (childResults != null && childResults.getLength() > 0) ? childResults.item(0) : null;
|
||||
Node ret = null;
|
||||
try {
|
||||
unmarshalledNode = XmlUtils.unmarshal(node);
|
||||
} catch (JAXBException e) {
|
||||
log.error("Cannot unmarshall " + node.getNodeName(), (Throwable)e);
|
||||
}
|
||||
if (unmarshalledNode != null)
|
||||
ret = toNode(context, unmarshalledNode, node.getNodeName(), content, doc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Node toNode(AbstractWmlConversionContext context, Object unmarshalledNode, String modelID, Node content, Document doc) {
|
||||
Node ret = null;
|
||||
try {
|
||||
Writer converter = this.writerInstances.get(modelID);
|
||||
if (converter == null) {
|
||||
log.warn("No writer registered for " + modelID);
|
||||
log.info("Generating wml from model.");
|
||||
Document docMarshalled = XmlUtils.marshaltoW3CDomDocument(unmarshalledNode);
|
||||
DocumentFragment docfrag = docMarshalled.createDocumentFragment();
|
||||
docfrag.appendChild(docMarshalled.getDocumentElement());
|
||||
ret = docfrag;
|
||||
} else {
|
||||
ret = converter.toNode(context, unmarshalledNode, content, context.getTransformState(modelID), doc);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Cannot convert " + unmarshalledNode, (Throwable)e);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
package org.docx4j.convert.out.common;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.Templates;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.convert.out.AbstractConversionSettings;
|
||||
import org.docx4j.events.EventFinished;
|
||||
import org.docx4j.events.StartEvent;
|
||||
import org.docx4j.events.WellKnownProcessSteps;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.utils.ResourceUtils;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
public abstract class AbstractXsltExporterDelegate<CS extends AbstractConversionSettings, CC extends AbstractWmlConversionContext> extends AbstractExporterDelegate<CS, CC> {
|
||||
protected String defaultTemplatesResource = null;
|
||||
|
||||
protected Templates defaultTemplates = null;
|
||||
|
||||
protected AbstractXsltExporterDelegate(String defaultTemplatesResource) {
|
||||
this.defaultTemplatesResource = defaultTemplatesResource;
|
||||
}
|
||||
|
||||
public void process(CS conversionSettings, CC conversionContext, OutputStream outputStream) throws Docx4JException {
|
||||
StartEvent startEvent = new StartEvent(conversionSettings.getWmlPackage(), WellKnownProcessSteps.OUT_XsltExporterDelegate);
|
||||
startEvent.publish();
|
||||
Document domDoc = getSourceDocument(conversionSettings, conversionContext);
|
||||
Templates templates = getTemplates(conversionSettings, conversionContext);
|
||||
Result intermediateResult = new StreamResult(outputStream);
|
||||
XmlUtils.transform(domDoc, templates, conversionContext.getXsltParameters(), intermediateResult);
|
||||
new EventFinished(startEvent).publish();
|
||||
}
|
||||
|
||||
protected abstract Document getSourceDocument(CS paramCS, CC paramCC) throws Docx4JException;
|
||||
|
||||
protected Templates getTemplates(CS conversionSettings, CC conversionContext) throws Docx4JException {
|
||||
Templates ret = (Templates)conversionSettings.getCustomXsltTemplates();
|
||||
return (ret == null) ? getDefaultTemplate() : ret;
|
||||
}
|
||||
|
||||
protected Templates getDefaultTemplate() throws Docx4JException {
|
||||
if (this.defaultTemplates == null)
|
||||
synchronized (XmlUtils.getTransformerFactory()) {
|
||||
if (this.defaultTemplates == null)
|
||||
this.defaultTemplates = loadDefaultTemplates();
|
||||
}
|
||||
return this.defaultTemplates;
|
||||
}
|
||||
|
||||
protected Templates loadDefaultTemplates() throws Docx4JException {
|
||||
Templates ret = null;
|
||||
Source xsltSource = null;
|
||||
try {
|
||||
xsltSource = new StreamSource(ResourceUtils.getResource(this.defaultTemplatesResource));
|
||||
ret = XmlUtils.getTransformerTemplate(xsltSource);
|
||||
} catch (IOException e) {
|
||||
throw new Docx4JException("Exception loading default template \"" + this.defaultTemplatesResource + "\", " + e.getMessage(), e);
|
||||
} catch (TransformerConfigurationException e) {
|
||||
throw new Docx4JException("Exception loading default template \"" + this.defaultTemplatesResource + "\", " + e.getMessage(), e);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package org.docx4j.convert.out.common;
|
||||
|
||||
import java.util.List;
|
||||
import org.docx4j.convert.out.common.preprocess.PageNumberInformation;
|
||||
import org.docx4j.model.structure.HeaderFooterPolicy;
|
||||
import org.docx4j.model.structure.SectionWrapper;
|
||||
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
|
||||
import org.docx4j.wml.BooleanDefaultTrue;
|
||||
import org.docx4j.wml.SectPr;
|
||||
|
||||
public class ConversionSectionWrapper extends SectionWrapper {
|
||||
protected List<Object> content = null;
|
||||
|
||||
protected String id = null;
|
||||
|
||||
protected PageNumberInformation pageNumberInformation = null;
|
||||
|
||||
public ConversionSectionWrapper(SectPr sectPr, HeaderFooterPolicy previousHF, RelationshipsPart rels, BooleanDefaultTrue evenAndOddHeaders, String id, List<Object> content) {
|
||||
super(sectPr, previousHF, rels, evenAndOddHeaders);
|
||||
this.id = id;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public List<Object> getContent() {
|
||||
return this.content;
|
||||
}
|
||||
|
||||
public void setPageNumberInformation(PageNumberInformation pageNumberInformation) {
|
||||
this.pageNumberInformation = pageNumberInformation;
|
||||
}
|
||||
|
||||
public PageNumberInformation getPageNumberInformation() {
|
||||
return this.pageNumberInformation;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
package org.docx4j.convert.out.common;
|
||||
|
||||
import java.util.List;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.model.structure.jaxb.ObjectFactory;
|
||||
import org.docx4j.model.structure.jaxb.Sections;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
public class ConversionSectionWrappers {
|
||||
protected List<ConversionSectionWrapper> conversionSections = null;
|
||||
|
||||
protected int currentSectionIndex = -1;
|
||||
|
||||
protected ConversionSectionWrapper currentSection = null;
|
||||
|
||||
public ConversionSectionWrappers(List<ConversionSectionWrapper> conversionSections) {
|
||||
this.conversionSections = conversionSections;
|
||||
}
|
||||
|
||||
public Sections createSections() {
|
||||
ObjectFactory factory = new ObjectFactory();
|
||||
Sections ret = factory.createSections();
|
||||
for (int i = 0; i < this.conversionSections.size(); i++)
|
||||
ret.getSection().add(createSection(factory, this.conversionSections.get(i)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
private Sections.Section createSection(ObjectFactory factory, ConversionSectionWrapper conversionSectionWrapper) {
|
||||
Sections.Section ret = factory.createSectionsSection();
|
||||
ret.setName(conversionSectionWrapper.getId());
|
||||
for (int i = 0; i < conversionSectionWrapper.getContent().size(); i++)
|
||||
ret.getAny().add(marshall(conversionSectionWrapper.getContent().get(i)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static Element marshall(Object o) {
|
||||
try {
|
||||
Document w3cDoc = XmlUtils.marshaltoW3CDomDocument(o);
|
||||
return w3cDoc.getDocumentElement();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public List<ConversionSectionWrapper> getList() {
|
||||
return this.conversionSections;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
this.currentSectionIndex = -1;
|
||||
}
|
||||
|
||||
public void next() {
|
||||
this.currentSectionIndex++;
|
||||
this.currentSection = null;
|
||||
if (this.currentSectionIndex >= 0 && this.currentSectionIndex < this.conversionSections.size())
|
||||
this.currentSection = this.conversionSections.get(this.currentSectionIndex);
|
||||
}
|
||||
|
||||
public ConversionSectionWrapper getCurrentSection() {
|
||||
if (this.currentSection != null)
|
||||
return this.currentSection;
|
||||
if (this.currentSectionIndex < 0)
|
||||
throw new IllegalArgumentException("Trying to access a section, but moveNext wasn't called");
|
||||
if (this.currentSectionIndex >= this.conversionSections.size())
|
||||
throw new IllegalArgumentException("Trying to access more sections than avaiable");
|
||||
throw new IllegalArgumentException("There is no current section");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package org.docx4j.convert.out.common;
|
||||
|
||||
import java.util.Set;
|
||||
import org.docx4j.convert.out.ConversionFeatures;
|
||||
import org.docx4j.convert.out.common.wrappers.ConversionSectionWrapperFactory;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CreateWrappers extends ConversionFeatures {
|
||||
private static Logger log = LoggerFactory.getLogger(CreateWrappers.class);
|
||||
|
||||
public static ConversionSectionWrappers process(WordprocessingMLPackage wmlPackage, Set<String> features) throws Docx4JException {
|
||||
ConversionSectionWrappers ret = null;
|
||||
boolean dummySections = false;
|
||||
boolean dummyPageNumbering = false;
|
||||
checkParams(wmlPackage, features);
|
||||
dummySections = !features.contains("pp.common.createsections");
|
||||
dummyPageNumbering = !features.contains("pp.common.pagenumbering");
|
||||
ret = ConversionSectionWrapperFactory.process(wmlPackage, dummySections, dummyPageNumbering);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package org.docx4j.convert.out.common;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
|
||||
public interface Exporter<T extends org.docx4j.convert.out.AbstractConversionSettings> {
|
||||
void export(T paramT, OutputStream paramOutputStream) throws Docx4JException;
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
package org.docx4j.convert.out.common;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import org.docx4j.convert.out.ConversionFeatures;
|
||||
import org.docx4j.convert.out.common.preprocess.BookmarkMover;
|
||||
import org.docx4j.convert.out.common.preprocess.Containerization;
|
||||
import org.docx4j.convert.out.common.preprocess.CoverPageSectPrMover;
|
||||
import org.docx4j.convert.out.common.preprocess.FieldsCombiner;
|
||||
import org.docx4j.convert.out.common.preprocess.FopWorkaroundDisablePageBreakOnFirstParagraph;
|
||||
import org.docx4j.convert.out.common.preprocess.FopWorkaroundReplacePageBreakInEachList;
|
||||
import org.docx4j.convert.out.common.preprocess.PageBreak;
|
||||
import org.docx4j.convert.out.common.preprocess.ParagraphStylesInTableFix;
|
||||
import org.docx4j.convert.out.common.preprocess.PartialDeepCopy;
|
||||
import org.docx4j.events.EventFinished;
|
||||
import org.docx4j.events.StartEvent;
|
||||
import org.docx4j.events.WellKnownProcessSteps;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.openpackaging.packages.OpcPackage;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Preprocess extends ConversionFeatures {
|
||||
private static Logger log = LoggerFactory.getLogger(Preprocess.class);
|
||||
|
||||
public static OpcPackage process(OpcPackage opcPackage, Set<String> features) throws Docx4JException {
|
||||
OpcPackage ret = opcPackage;
|
||||
Set<String> relationshipTypes = null;
|
||||
checkParams(opcPackage, features);
|
||||
relationshipTypes = createRelationshipTypes(features);
|
||||
if (features.contains("pp.common.deepcopy")) {
|
||||
ret = PartialDeepCopy.process(opcPackage, relationshipTypes);
|
||||
if (ret instanceof WordprocessingMLPackage)
|
||||
log.debug("Results of PP_COMMON_DEEP_COPY: " + ((WordprocessingMLPackage)ret).getMainDocumentPart().getXML());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected static Set<String> createRelationshipTypes(Set<String> features) {
|
||||
Set<String> relationshipTypes = new TreeSet<String>();
|
||||
if (features.contains("pp.common.movebookmarks") || features.contains("pp.common.containerization") || features.contains("pp.common.combinefields")) {
|
||||
relationshipTypes.add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument");
|
||||
relationshipTypes.add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/header");
|
||||
relationshipTypes.add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer");
|
||||
relationshipTypes.add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes");
|
||||
relationshipTypes.add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes");
|
||||
relationshipTypes.add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments");
|
||||
}
|
||||
if (features.contains("pp.common.movepagebreak"))
|
||||
relationshipTypes.add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument");
|
||||
return relationshipTypes;
|
||||
}
|
||||
|
||||
public static WordprocessingMLPackage process(WordprocessingMLPackage wmlPackage, Set<String> features) throws Docx4JException {
|
||||
WordprocessingMLPackage ret = (WordprocessingMLPackage)process((OpcPackage)wmlPackage, features);
|
||||
StartEvent startEvent = new StartEvent(ret, WellKnownProcessSteps.CONVERT_PREPROCESS);
|
||||
startEvent.publish();
|
||||
if (features.contains("pp.common.combinefields")) {
|
||||
log.debug("PP_COMMON_COMBINE_FIELDS");
|
||||
FieldsCombiner.process(ret);
|
||||
}
|
||||
if (features.contains("pp.common.movebookmarks")) {
|
||||
log.debug("PP_COMMON_MOVE_BOOKMARKS");
|
||||
BookmarkMover.process(ret);
|
||||
}
|
||||
if (features.contains("pp.common.movepagebreak")) {
|
||||
log.debug("PP_COMMON_MOVE_PAGEBREAK");
|
||||
PageBreak.process(ret);
|
||||
}
|
||||
if (features.contains("pp.common.coverpagemovesectpr")) {
|
||||
log.debug("PP_COMMON_COVERPAGE_MOVE_SECTPR");
|
||||
CoverPageSectPrMover.process(ret);
|
||||
}
|
||||
if (features.contains("pp.common.containerization")) {
|
||||
log.debug("PP_COMMON_CONTAINERIZATION");
|
||||
Containerization.process(ret);
|
||||
}
|
||||
if (features.contains("pp.apachefop.disablepagebreakfirstparagraph")) {
|
||||
log.debug("PP_APACHEFOP_DISABLE_PAGEBREAK_FIRST_PARAGRAPH");
|
||||
FopWorkaroundDisablePageBreakOnFirstParagraph.process(ret);
|
||||
}
|
||||
if (features.contains("pp.apachefop.disablepagebreaklistitem")) {
|
||||
log.debug("PP_APACHEFOP_DISABLE_PAGEBREAK_LIST_ITEM");
|
||||
FopWorkaroundReplacePageBreakInEachList.process(ret);
|
||||
}
|
||||
if (features.contains("pp.common.tbl-p-style-fix")) {
|
||||
log.debug("PP_COMMON_TABLE_PARAGRAPH_STYLE_FIX");
|
||||
ParagraphStylesInTableFix.process(ret);
|
||||
}
|
||||
log.debug("Results of preprocessing: " + ret.getMainDocumentPart().getXML());
|
||||
new EventFinished(startEvent).publish();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package org.docx4j.convert.out.common;
|
||||
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.convert.out.AbstractConversionSettings;
|
||||
import org.docx4j.jaxb.Context;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
public class WmlXsltExporterDelegate<CS extends AbstractConversionSettings, CC extends AbstractWmlConversionContext> extends AbstractXsltExporterDelegate<CS, CC> {
|
||||
public WmlXsltExporterDelegate(String defaultTemplatesResource) {
|
||||
super(defaultTemplatesResource);
|
||||
}
|
||||
|
||||
protected Document getSourceDocument(CS conversionSettings, CC conversionContext) throws Docx4JException {
|
||||
ConversionSectionWrappers conversionSectionWrappers = conversionContext.getSections();
|
||||
Document ret = XmlUtils.marshaltoW3CDomDocument(conversionSectionWrappers.createSections(), Context.jcSectionModel);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package org.docx4j.convert.out.common;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
public interface Writer {
|
||||
String getID();
|
||||
|
||||
Node toNode(AbstractWmlConversionContext paramAbstractWmlConversionContext, Object paramObject, Node paramNode, TransformState paramTransformState, Document paramDocument) throws TransformerException;
|
||||
|
||||
TransformState createTransformState();
|
||||
|
||||
public static interface TransformState {}
|
||||
}
|
||||
|
|
@ -0,0 +1,290 @@
|
|||
package org.docx4j.convert.out.common;
|
||||
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.jaxb.Context;
|
||||
import org.docx4j.jaxb.JaxbValidationEventHandler;
|
||||
import org.docx4j.model.styles.StyleUtil;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.openpackaging.parts.Part;
|
||||
import org.docx4j.wml.CTFootnotes;
|
||||
import org.docx4j.wml.CTFtnEdn;
|
||||
import org.docx4j.wml.FldChar;
|
||||
import org.docx4j.wml.Ftr;
|
||||
import org.docx4j.wml.Hdr;
|
||||
import org.docx4j.wml.PPr;
|
||||
import org.docx4j.wml.ParaRPr;
|
||||
import org.docx4j.wml.RPr;
|
||||
import org.docx4j.wml.STFldCharType;
|
||||
import org.docx4j.wml.Text;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.w3c.dom.traversal.NodeIterator;
|
||||
|
||||
public class XsltCommonFunctions {
|
||||
private static Logger log = LoggerFactory.getLogger(XsltCommonFunctions.class);
|
||||
|
||||
public static DocumentFragment fontSelector(AbstractWmlConversionContext conversionContext, NodeIterator pPrNodeIt, NodeIterator rPrNodeIt, NodeIterator textNodeIt) {
|
||||
PPr pPr = null;
|
||||
RPr rPr = null;
|
||||
Text text = null;
|
||||
Node n = pPrNodeIt.nextNode();
|
||||
if (n != null)
|
||||
try {
|
||||
Unmarshaller u = Context.jc.createUnmarshaller();
|
||||
u.setEventHandler(new JaxbValidationEventHandler());
|
||||
Object jaxb = u.unmarshal(n);
|
||||
pPr = (PPr)jaxb;
|
||||
} catch (ClassCastException e) {
|
||||
log.error("Couldn't cast to RPr!");
|
||||
} catch (JAXBException e) {
|
||||
log.error(e.getMessage(), (Throwable)e);
|
||||
}
|
||||
n = rPrNodeIt.nextNode();
|
||||
if (n != null)
|
||||
try {
|
||||
Unmarshaller u = Context.jc.createUnmarshaller();
|
||||
u.setEventHandler(new JaxbValidationEventHandler());
|
||||
Object jaxb = u.unmarshal(n);
|
||||
if (jaxb instanceof RPr) {
|
||||
rPr = (RPr)jaxb;
|
||||
} else if (jaxb instanceof ParaRPr) {
|
||||
rPr = conversionContext.getPropertyResolver().getEffectiveRPr(null, pPr);
|
||||
StyleUtil.apply((ParaRPr)jaxb, rPr);
|
||||
}
|
||||
} catch (ClassCastException e) {
|
||||
log.error("Couldn't cast to RPr!");
|
||||
} catch (JAXBException e) {
|
||||
log.error(e.getMessage(), (Throwable)e);
|
||||
}
|
||||
n = textNodeIt.nextNode();
|
||||
if (n != null)
|
||||
try {
|
||||
Unmarshaller u = Context.jc.createUnmarshaller();
|
||||
u.setEventHandler(new JaxbValidationEventHandler());
|
||||
Object jaxb = u.unmarshal(n);
|
||||
text = (Text)jaxb;
|
||||
} catch (ClassCastException e) {
|
||||
log.error("Couldn't cast to Text!");
|
||||
} catch (JAXBException e) {
|
||||
log.error(e.getMessage(), (Throwable)e);
|
||||
}
|
||||
return (DocumentFragment)conversionContext.getRunFontSelector().fontSelector(pPr, rPr, text);
|
||||
}
|
||||
|
||||
public static Node toNode(AbstractWmlConversionContext context, Node node, NodeList childResults) {
|
||||
return context.getWriterRegistry().toNode(context, node, childResults);
|
||||
}
|
||||
|
||||
public static int getNextFootnoteNumber(AbstractWmlConversionContext context) {
|
||||
return context.getNextFootnoteNumber();
|
||||
}
|
||||
|
||||
public static Node getFootnote(AbstractWmlConversionContext context, String id) {
|
||||
WordprocessingMLPackage wmlPackage = context.getWmlPackage();
|
||||
CTFootnotes footnotes = wmlPackage.getMainDocumentPart().getFootnotesPart().getJaxbElement();
|
||||
int pos = Integer.parseInt(id);
|
||||
CTFtnEdn ftn = footnotes.getFootnote().get(pos);
|
||||
Document d = XmlUtils.marshaltoW3CDomDocument(ftn, Context.jc, "http://schemas.openxmlformats.org/wordprocessingml/2006/main", "footnote", CTFtnEdn.class);
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("Footnote " + id + ": " + XmlUtils.w3CDomNodeToString(d));
|
||||
return d;
|
||||
}
|
||||
|
||||
public static int getNextEndnoteNumber(AbstractWmlConversionContext context) {
|
||||
return context.getNextEndnoteNumber();
|
||||
}
|
||||
|
||||
public static void setCurrentPart(AbstractWmlConversionContext context, Part currentPart) {
|
||||
context.setCurrentPart(currentPart);
|
||||
}
|
||||
|
||||
public static Part getCurrentPart(AbstractWmlConversionContext context) {
|
||||
return context.getCurrentPart();
|
||||
}
|
||||
|
||||
public static void setCurrentPartMainDocument(AbstractWmlConversionContext context) {
|
||||
context.setCurrentPartMainDocument();
|
||||
}
|
||||
|
||||
public static void setCurrentPartDefaultHeader(AbstractWmlConversionContext context) {
|
||||
ConversionSectionWrapper currentSection = context.getSections().getCurrentSection();
|
||||
context.setCurrentPart(currentSection.getHeaderFooterPolicy().getDefaultHeader());
|
||||
}
|
||||
|
||||
public static void setCurrentPartDefaultFooter(AbstractWmlConversionContext context) {
|
||||
ConversionSectionWrapper currentSection = context.getSections().getCurrentSection();
|
||||
context.setCurrentPart(currentSection.getHeaderFooterPolicy().getDefaultFooter());
|
||||
}
|
||||
|
||||
public static void moveNextSection(AbstractWmlConversionContext context) {
|
||||
context.getSections().next();
|
||||
}
|
||||
|
||||
public static boolean hasDefaultHeaderOrFooter(AbstractWmlConversionContext context) {
|
||||
ConversionSectionWrapper currentSection = context.getSections().getCurrentSection();
|
||||
return (currentSection.getHeaderFooterPolicy().getDefaultHeader() != null || currentSection.getHeaderFooterPolicy().getDefaultFooter() != null);
|
||||
}
|
||||
|
||||
public static boolean hasFirstHeader(AbstractWmlConversionContext context) {
|
||||
ConversionSectionWrapper currentSection = context.getSections().getCurrentSection();
|
||||
return (currentSection.getHeaderFooterPolicy().getFirstHeader() != null);
|
||||
}
|
||||
|
||||
public static boolean hasEvenHeader(AbstractWmlConversionContext context) {
|
||||
ConversionSectionWrapper currentSection = context.getSections().getCurrentSection();
|
||||
return (currentSection.getHeaderFooterPolicy().getEvenHeader() != null);
|
||||
}
|
||||
|
||||
public static boolean hasDefaultHeader(AbstractWmlConversionContext context) {
|
||||
ConversionSectionWrapper currentSection = context.getSections().getCurrentSection();
|
||||
return (currentSection.getHeaderFooterPolicy().getDefaultHeader() != null);
|
||||
}
|
||||
|
||||
public static boolean hasFirstFooter(AbstractWmlConversionContext context) {
|
||||
ConversionSectionWrapper currentSection = context.getSections().getCurrentSection();
|
||||
return (currentSection.getHeaderFooterPolicy().getFirstFooter() != null);
|
||||
}
|
||||
|
||||
public static boolean hasEvenFooter(AbstractWmlConversionContext context) {
|
||||
ConversionSectionWrapper currentSection = context.getSections().getCurrentSection();
|
||||
return (currentSection.getHeaderFooterPolicy().getEvenFooter() != null);
|
||||
}
|
||||
|
||||
public static boolean hasDefaultFooter(AbstractWmlConversionContext context) {
|
||||
ConversionSectionWrapper currentSection = context.getSections().getCurrentSection();
|
||||
return (currentSection.getHeaderFooterPolicy().getDefaultFooter() != null);
|
||||
}
|
||||
|
||||
public static Node getFirstHeader(AbstractWmlConversionContext context) {
|
||||
ConversionSectionWrapper currentSection = context.getSections().getCurrentSection();
|
||||
Hdr hdr = currentSection.getHeaderFooterPolicy().getFirstHeader().getJaxbElement();
|
||||
return XmlUtils.marshaltoW3CDomDocument(hdr);
|
||||
}
|
||||
|
||||
public static Node getFirstFooter(AbstractWmlConversionContext context) {
|
||||
ConversionSectionWrapper currentSection = context.getSections().getCurrentSection();
|
||||
Ftr ftr = currentSection.getHeaderFooterPolicy().getFirstFooter().getJaxbElement();
|
||||
return XmlUtils.marshaltoW3CDomDocument(ftr);
|
||||
}
|
||||
|
||||
public static Node getEvenHeader(AbstractWmlConversionContext context) {
|
||||
ConversionSectionWrapper currentSection = context.getSections().getCurrentSection();
|
||||
Hdr hdr = currentSection.getHeaderFooterPolicy().getEvenHeader().getJaxbElement();
|
||||
return XmlUtils.marshaltoW3CDomDocument(hdr);
|
||||
}
|
||||
|
||||
public static Node getEvenFooter(AbstractWmlConversionContext context) {
|
||||
ConversionSectionWrapper currentSection = context.getSections().getCurrentSection();
|
||||
Ftr ftr = currentSection.getHeaderFooterPolicy().getEvenFooter().getJaxbElement();
|
||||
return XmlUtils.marshaltoW3CDomDocument(ftr);
|
||||
}
|
||||
|
||||
public static Node getDefaultHeader(AbstractWmlConversionContext context) {
|
||||
ConversionSectionWrapper currentSection = context.getSections().getCurrentSection();
|
||||
Hdr hdr = currentSection.getHeaderFooterPolicy().getDefaultHeader().getJaxbElement();
|
||||
return XmlUtils.marshaltoW3CDomDocument(hdr);
|
||||
}
|
||||
|
||||
public static Node getDefaultFooter(AbstractWmlConversionContext context) {
|
||||
ConversionSectionWrapper currentSection = context.getSections().getCurrentSection();
|
||||
Ftr ftr = currentSection.getHeaderFooterPolicy().getDefaultFooter().getJaxbElement();
|
||||
return XmlUtils.marshaltoW3CDomDocument(ftr);
|
||||
}
|
||||
|
||||
public static void inFirstHeader(AbstractWmlConversionContext context) {
|
||||
ConversionSectionWrapper currentSection = context.getSections().getCurrentSection();
|
||||
setCurrentPart(context, currentSection.getHeaderFooterPolicy().getFirstHeader());
|
||||
}
|
||||
|
||||
public static void inEvenHeader(AbstractWmlConversionContext context) {
|
||||
ConversionSectionWrapper currentSection = context.getSections().getCurrentSection();
|
||||
setCurrentPart(context, currentSection.getHeaderFooterPolicy().getEvenHeader());
|
||||
}
|
||||
|
||||
public static void inDefaultHeader(AbstractWmlConversionContext context) {
|
||||
ConversionSectionWrapper currentSection = context.getSections().getCurrentSection();
|
||||
setCurrentPart(context, currentSection.getHeaderFooterPolicy().getDefaultHeader());
|
||||
}
|
||||
|
||||
public static void inFirstFooter(AbstractWmlConversionContext context) {
|
||||
ConversionSectionWrapper currentSection = context.getSections().getCurrentSection();
|
||||
setCurrentPart(context, currentSection.getHeaderFooterPolicy().getFirstFooter());
|
||||
}
|
||||
|
||||
public static void inEvenFooter(AbstractWmlConversionContext context) {
|
||||
ConversionSectionWrapper currentSection = context.getSections().getCurrentSection();
|
||||
setCurrentPart(context, currentSection.getHeaderFooterPolicy().getEvenFooter());
|
||||
}
|
||||
|
||||
public static void inDefaultFooter(AbstractWmlConversionContext context) {
|
||||
ConversionSectionWrapper currentSection = context.getSections().getCurrentSection();
|
||||
setCurrentPart(context, currentSection.getHeaderFooterPolicy().getDefaultFooter());
|
||||
}
|
||||
|
||||
public static boolean hasEndnotesPart(AbstractWmlConversionContext context) {
|
||||
return context.getWmlPackage().getMainDocumentPart().hasEndnotesPart();
|
||||
}
|
||||
|
||||
public static Node getEndnotes(AbstractWmlConversionContext context) {
|
||||
return XmlUtils.marshaltoW3CDomDocument(context.getWmlPackage().getMainDocumentPart().getEndNotesPart().getJaxbElement());
|
||||
}
|
||||
|
||||
public static boolean hasFootnotesPart(AbstractWmlConversionContext context) {
|
||||
return context.getWmlPackage().getMainDocumentPart().hasFootnotesPart();
|
||||
}
|
||||
|
||||
public static Node getFootnotes(AbstractWmlConversionContext context) {
|
||||
return XmlUtils.marshaltoW3CDomDocument(context.getWmlPackage().getMainDocumentPart().getFootnotesPart().getJaxbElement());
|
||||
}
|
||||
|
||||
public static void updateComplexFieldDefinition(AbstractWmlConversionContext context, NodeIterator fldCharNodeIt) {
|
||||
FldChar field = null;
|
||||
Node node = fldCharNodeIt.nextNode();
|
||||
try {
|
||||
field = (FldChar)XmlUtils.unmarshal(node, Context.jc, FldChar.class);
|
||||
} catch (JAXBException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
STFldCharType fieldCharType = field.getFldCharType();
|
||||
if (fieldCharType == null) {
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("Ignoring unrecognised: " + XmlUtils.w3CDomNodeToString(node));
|
||||
} else {
|
||||
context.updateComplexFieldDefinition(fieldCharType);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isInComplexFieldDefinition(AbstractWmlConversionContext context) {
|
||||
return context.isInComplexFieldDefinition();
|
||||
}
|
||||
|
||||
public static DocumentFragment notImplemented(AbstractConversionContext context, NodeIterator nodes, String message) {
|
||||
return context.getMessageWriter().notImplemented(context, nodes, message);
|
||||
}
|
||||
|
||||
public static DocumentFragment message(AbstractConversionContext context, String message) {
|
||||
return context.getMessageWriter().message(context, message);
|
||||
}
|
||||
|
||||
public static boolean isLoggingEnabled(AbstractConversionContext context) {
|
||||
return context.getLog().isDebugEnabled();
|
||||
}
|
||||
|
||||
public static void logDebug(AbstractConversionContext context, String message) {
|
||||
context.getLog().debug(message);
|
||||
}
|
||||
|
||||
public static void logInfo(AbstractConversionContext context, String message) {
|
||||
context.getLog().info(message);
|
||||
}
|
||||
|
||||
public static void logWarn(AbstractConversionContext context, String message) {
|
||||
context.getLog().warn(message);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
package org.docx4j.convert.out.common.preprocess;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.namespace.QName;
|
||||
import org.docx4j.TraversalUtil;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.jaxb.Context;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.utils.AbstractTraversalUtilVisitorCallback;
|
||||
import org.docx4j.wml.CTBookmark;
|
||||
import org.docx4j.wml.CTMarkupRange;
|
||||
import org.docx4j.wml.P;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class BookmarkMover {
|
||||
protected static Logger log = LoggerFactory.getLogger(BookmarkMover.class);
|
||||
|
||||
public static void process(WordprocessingMLPackage wmlPackage) {
|
||||
TraversalUtil.visit(wmlPackage, false, new BookmarkMoverVisitor());
|
||||
}
|
||||
|
||||
protected static class BookmarkMoverVisitor extends AbstractTraversalUtilVisitorCallback {
|
||||
protected static final QName QNAME_BOOKMARK_START = new QName("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "bookmarkStart");
|
||||
|
||||
protected static final QName QNAME_BOOKMARK_END = new QName("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "bookmarkEnd");
|
||||
|
||||
protected List<Object> bookmarksStartToMove = new ArrayList();
|
||||
|
||||
protected Set<BigInteger> bookmarksEndToRemove = new TreeSet<BigInteger>();
|
||||
|
||||
protected P currentParagraph = null;
|
||||
|
||||
public void walkJAXBElements(Object parent) {
|
||||
List<Object> srcChildren = getChildren(XmlUtils.unwrap(parent));
|
||||
List<Object> destChildren = null;
|
||||
Object child = null;
|
||||
if (srcChildren != null && !srcChildren.isEmpty()) {
|
||||
destChildren = new ArrayList(srcChildren.size());
|
||||
for (int c = 0; c < srcChildren.size(); c++) {
|
||||
child = srcChildren.get(c);
|
||||
if (isBookmarkStart(child)) {
|
||||
if (this.currentParagraph == null) {
|
||||
appendBookmarksToMove(child);
|
||||
} else {
|
||||
destChildren.add(child);
|
||||
}
|
||||
} else if (isBookmarkEnd(child)) {
|
||||
if (!removeBookmarkEnd(child))
|
||||
destChildren.add(child);
|
||||
} else {
|
||||
destChildren.add(child);
|
||||
if (isParagraph(child)) {
|
||||
try {
|
||||
this.currentParagraph = (P)child;
|
||||
walkJAXBElements(child);
|
||||
moveBookmarks(child);
|
||||
this.currentParagraph = null;
|
||||
} finally {
|
||||
this.currentParagraph = null;
|
||||
}
|
||||
} else {
|
||||
walkJAXBElements(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (destChildren.size() != srcChildren.size()) {
|
||||
srcChildren.clear();
|
||||
srcChildren.addAll(destChildren);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBookmarkStart(Object child) {
|
||||
return (child instanceof JAXBElement && ((JAXBElement)child).getName().equals(QNAME_BOOKMARK_START));
|
||||
}
|
||||
|
||||
private void appendBookmarksToMove(Object child) {
|
||||
CTBookmark bm = (CTBookmark)XmlUtils.unwrap(child);
|
||||
JAXBElement<CTMarkupRange> jaxbBmEnd = null;
|
||||
CTMarkupRange bmEnd = null;
|
||||
this.bookmarksStartToMove.add(child);
|
||||
bmEnd = Context.getWmlObjectFactory().createCTMarkupRange();
|
||||
bmEnd.setId(bm.getId());
|
||||
jaxbBmEnd = Context.getWmlObjectFactory().createPBookmarkEnd(bmEnd);
|
||||
this.bookmarksStartToMove.add(jaxbBmEnd);
|
||||
this.bookmarksEndToRemove.add(bm.getId());
|
||||
}
|
||||
|
||||
private boolean isBookmarkEnd(Object child) {
|
||||
return (child instanceof JAXBElement && ((JAXBElement)child).getName().equals(QNAME_BOOKMARK_END));
|
||||
}
|
||||
|
||||
private boolean removeBookmarkEnd(Object child) {
|
||||
CTMarkupRange bmEnd = (CTMarkupRange)XmlUtils.unwrap(child);
|
||||
if (bmEnd.getId() == null)
|
||||
return true;
|
||||
return this.bookmarksEndToRemove.remove(bmEnd.getId());
|
||||
}
|
||||
|
||||
private boolean isParagraph(Object child) {
|
||||
return child instanceof P;
|
||||
}
|
||||
|
||||
private void moveBookmarks(Object child) {
|
||||
P p = null;
|
||||
List<Object> content = null;
|
||||
if (!this.bookmarksStartToMove.isEmpty()) {
|
||||
p = (P)XmlUtils.unwrap(child);
|
||||
content = p.getContent();
|
||||
content.addAll(0, this.bookmarksStartToMove);
|
||||
this.bookmarksStartToMove.clear();
|
||||
}
|
||||
}
|
||||
|
||||
protected List<Object> apply(Object child, Object parent, List children) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,280 @@
|
|||
package org.docx4j.convert.out.common.preprocess;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.jaxb.Context;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.CommentsPart;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.EndnotesPart;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.FooterPart;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.FootnotesPart;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.HeaderPart;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
|
||||
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
|
||||
import org.docx4j.relationships.Relationship;
|
||||
import org.docx4j.wml.CTBorder;
|
||||
import org.docx4j.wml.CTShd;
|
||||
import org.docx4j.wml.Comments;
|
||||
import org.docx4j.wml.P;
|
||||
import org.docx4j.wml.PPrBase;
|
||||
import org.docx4j.wml.R;
|
||||
import org.docx4j.wml.RPr;
|
||||
import org.docx4j.wml.SdtBlock;
|
||||
import org.docx4j.wml.SdtContentBlock;
|
||||
import org.docx4j.wml.SdtPr;
|
||||
import org.docx4j.wml.Tag;
|
||||
import org.docx4j.wml.Tbl;
|
||||
import org.docx4j.wml.Tc;
|
||||
import org.docx4j.wml.Tr;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Containerization {
|
||||
private static Logger log = LoggerFactory.getLogger(Containerization.class);
|
||||
|
||||
public static final String TAG_SHADING = "XSLT_Shd";
|
||||
|
||||
public static final String TAG_BORDERS = "XSLT_PBdr";
|
||||
|
||||
public static final String TAG_RPR = "XSLT_RPr";
|
||||
|
||||
public static void process(WordprocessingMLPackage wmlPackage) {
|
||||
MainDocumentPart mainDocument = null;
|
||||
RelationshipsPart relPart = null;
|
||||
List<Relationship> relList = null;
|
||||
List<Object> elementList = null;
|
||||
mainDocument = wmlPackage.getMainDocumentPart();
|
||||
groupAdjacentBorders(mainDocument.getJaxbElement().getBody().getContent());
|
||||
relPart = mainDocument.getRelationshipsPart();
|
||||
relList = relPart.getRelationships().getRelationship();
|
||||
for (Relationship rs : relList) {
|
||||
elementList = null;
|
||||
if ("http://schemas.openxmlformats.org/officeDocument/2006/relationships/header".equals(rs.getType())) {
|
||||
elementList = ((HeaderPart)relPart.getPart(rs)).getJaxbElement().getContent();
|
||||
} else if ("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer".equals(rs.getType())) {
|
||||
elementList = ((FooterPart)relPart.getPart(rs)).getJaxbElement().getContent();
|
||||
} else if ("http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes".equals(rs.getType())) {
|
||||
elementList = new ArrayList();
|
||||
elementList.addAll(((EndnotesPart)relPart.getPart(rs)).getJaxbElement().getEndnote());
|
||||
} else if ("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes".equals(rs.getType())) {
|
||||
elementList = new ArrayList();
|
||||
elementList.addAll(((FootnotesPart)relPart.getPart(rs)).getJaxbElement().getFootnote());
|
||||
} else if ("http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments".equals(rs.getType())) {
|
||||
elementList = new ArrayList();
|
||||
for (Comments.Comment comment : ((CommentsPart)relPart.getPart(rs)).getJaxbElement().getComment())
|
||||
elementList.addAll(comment.getEGBlockLevelElts());
|
||||
}
|
||||
if (elementList != null && !elementList.isEmpty())
|
||||
groupAdjacentBorders(elementList);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void groupAdjacentBorders(List<Object> content) {
|
||||
List<Object> groupedContent = null;
|
||||
groupedContent = groupBodyContent(content);
|
||||
if (groupedContent != null) {
|
||||
content.clear();
|
||||
content.addAll(groupedContent);
|
||||
}
|
||||
}
|
||||
|
||||
private static void groupTable(Tbl table) {
|
||||
List<Object> cellElts = null;
|
||||
Tr tr = null;
|
||||
Tc tc = null;
|
||||
for (Object elemTr : table.getContent()) {
|
||||
if (elemTr instanceof JAXBElement)
|
||||
elemTr = ((JAXBElement)elemTr).getValue();
|
||||
if (elemTr instanceof Tr) {
|
||||
tr = (Tr)elemTr;
|
||||
if (tr.getContent() != null)
|
||||
for (Object elemCe : tr.getContent()) {
|
||||
if (elemCe instanceof JAXBElement)
|
||||
elemCe = ((JAXBElement)elemCe).getValue();
|
||||
if (elemCe instanceof Tc) {
|
||||
tc = (Tc)elemCe;
|
||||
if (tc.getContent() != null) {
|
||||
cellElts = groupBodyContent(tc.getContent());
|
||||
if (cellElts != null) {
|
||||
tc.getContent().clear();
|
||||
tc.getContent().addAll(cellElts);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Object> groupBodyContent(List<Object> bodyElts) {
|
||||
List<Object> resultElts = new ArrayList();
|
||||
List<Object> paragraphElts = null;
|
||||
SdtBlock sdtBorders = null;
|
||||
SdtBlock sdtShading = null;
|
||||
PPrBase.PBdr lastBorders = null;
|
||||
PPrBase.PBdr currentBorders = null;
|
||||
CTShd lastShading = null;
|
||||
CTShd currentShading = null;
|
||||
P paragraph = null;
|
||||
for (Object o : bodyElts) {
|
||||
if (o instanceof JAXBElement)
|
||||
o = ((JAXBElement)o).getValue();
|
||||
if (o instanceof P) {
|
||||
paragraph = (P)o;
|
||||
paragraphElts = groupRuns(paragraph.getContent());
|
||||
paragraph.getContent().clear();
|
||||
if (paragraphElts != null)
|
||||
paragraph.getContent().addAll(paragraphElts);
|
||||
currentBorders = null;
|
||||
currentShading = null;
|
||||
if (paragraph.getPPr() != null) {
|
||||
currentBorders = paragraph.getPPr().getPBdr();
|
||||
currentShading = paragraph.getPPr().getShd();
|
||||
}
|
||||
if (bordersChanged(currentBorders, lastBorders))
|
||||
if (currentBorders == null) {
|
||||
sdtBorders = null;
|
||||
} else {
|
||||
sdtBorders = createSdt("XSLT_PBdr");
|
||||
resultElts.add(sdtBorders);
|
||||
}
|
||||
if (shadingChanged(currentShading, lastShading))
|
||||
if (currentShading == null) {
|
||||
sdtShading = null;
|
||||
} else {
|
||||
sdtShading = createSdt("XSLT_Shd");
|
||||
if (sdtBorders != null) {
|
||||
sdtBorders.getSdtContent().getContent().add(sdtShading);
|
||||
} else {
|
||||
resultElts.add(sdtShading);
|
||||
}
|
||||
}
|
||||
} else if (o instanceof Tbl) {
|
||||
groupTable((Tbl)o);
|
||||
}
|
||||
if (sdtShading != null) {
|
||||
sdtShading.getSdtContent().getContent().add(o);
|
||||
} else if (sdtBorders != null) {
|
||||
sdtBorders.getSdtContent().getContent().add(o);
|
||||
} else {
|
||||
resultElts.add(o);
|
||||
}
|
||||
lastBorders = currentBorders;
|
||||
lastShading = currentShading;
|
||||
}
|
||||
return resultElts;
|
||||
}
|
||||
|
||||
private static List<Object> groupRuns(List<Object> paragraphElts) {
|
||||
List<Object> resultElts = new ArrayList();
|
||||
SdtBlock currentBlock = null;
|
||||
CTBorder lastBorder = null;
|
||||
CTBorder currentBorder = null;
|
||||
R run = null;
|
||||
for (Object o : paragraphElts) {
|
||||
if (o instanceof R) {
|
||||
run = (R)o;
|
||||
currentBorder = null;
|
||||
if (run.getRPr() != null)
|
||||
currentBorder = run.getRPr().getBdr();
|
||||
if (borderChanged(currentBorder, lastBorder)) {
|
||||
appendRun(currentBlock, resultElts);
|
||||
currentBlock = null;
|
||||
if (currentBorder != null)
|
||||
currentBlock = createSdt("XSLT_RPr", run.getRPr());
|
||||
}
|
||||
}
|
||||
if (currentBlock != null) {
|
||||
currentBlock.getSdtContent().getContent().add(o);
|
||||
} else {
|
||||
resultElts.add(o);
|
||||
}
|
||||
lastBorder = currentBorder;
|
||||
}
|
||||
appendRun(currentBlock, resultElts);
|
||||
return resultElts;
|
||||
}
|
||||
|
||||
private static void appendRun(SdtBlock currentBlock, List<Object> resultElts) {
|
||||
List<Object> blkElements = null;
|
||||
R run = null;
|
||||
RPr blockRPr = null;
|
||||
if (currentBlock != null) {
|
||||
blkElements = currentBlock.getSdtContent().getContent();
|
||||
if (blkElements.size() == 1) {
|
||||
resultElts.add(blkElements.get(0));
|
||||
} else {
|
||||
resultElts.add(currentBlock);
|
||||
blockRPr = findBlockRPr(currentBlock);
|
||||
for (Object elem : blkElements) {
|
||||
if (elem instanceof R) {
|
||||
run = (R)elem;
|
||||
if (run.getRPr() != null) {
|
||||
run.getRPr().setBdr(null);
|
||||
if (!shadingChanged(blockRPr.getShd(), run.getRPr().getShd()))
|
||||
run.getRPr().setShd(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static RPr findBlockRPr(SdtBlock currentBlock) {
|
||||
for (Object obj : currentBlock.getSdtPr().getRPrOrAliasOrLock()) {
|
||||
if (obj instanceof RPr)
|
||||
return (RPr)obj;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static SdtBlock createSdt(String tagVal) {
|
||||
return createSdt(tagVal, null);
|
||||
}
|
||||
|
||||
private static SdtBlock createSdt(String tagVal, RPr rPr) {
|
||||
SdtBlock sdtBlock = Context.getWmlObjectFactory().createSdtBlock();
|
||||
SdtPr sdtPr = Context.getWmlObjectFactory().createSdtPr();
|
||||
sdtBlock.setSdtPr(sdtPr);
|
||||
SdtContentBlock sdtContent = Context.getWmlObjectFactory().createSdtContentBlock();
|
||||
sdtBlock.setSdtContent(sdtContent);
|
||||
Tag tag = Context.getWmlObjectFactory().createTag();
|
||||
tag.setVal(tagVal);
|
||||
sdtPr.setTag(tag);
|
||||
if (rPr != null)
|
||||
sdtPr.getRPrOrAliasOrLock().add(XmlUtils.<RPr>deepCopy(rPr));
|
||||
return sdtBlock;
|
||||
}
|
||||
|
||||
private static boolean bordersChanged(PPrBase.PBdr currentBorders, PPrBase.PBdr lastBorders) {
|
||||
if (currentBorders != lastBorders) {
|
||||
if (currentBorders != null && lastBorders != null)
|
||||
return (borderChanged(currentBorders.getTop(), lastBorders.getTop()) || borderChanged(currentBorders.getBottom(), lastBorders.getBottom()));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean borderChanged(CTBorder currentBorder, CTBorder lastBorder) {
|
||||
if (currentBorder != lastBorder) {
|
||||
if (currentBorder != null && lastBorder != null)
|
||||
return !currentBorder.getVal().equals(lastBorder.getVal());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean shadingChanged(CTShd currentShading, CTShd lastShading) {
|
||||
if (currentShading == null && lastShading == null)
|
||||
return false;
|
||||
if (currentShading == null && lastShading != null)
|
||||
return true;
|
||||
if (currentShading != null && lastShading == null)
|
||||
return true;
|
||||
if (currentShading.getFill() == null || lastShading.getFill() == null)
|
||||
return true;
|
||||
return !currentShading.getFill().equals(lastShading.getFill());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
package org.docx4j.convert.out.common.preprocess;
|
||||
|
||||
import java.util.List;
|
||||
import org.docx4j.jaxb.Context;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.wml.Body;
|
||||
import org.docx4j.wml.P;
|
||||
import org.docx4j.wml.PPr;
|
||||
import org.docx4j.wml.SdtElement;
|
||||
import org.docx4j.wml.SectPr;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CoverPageSectPrMover {
|
||||
private static Logger log = LoggerFactory.getLogger(CoverPageSectPrMover.class);
|
||||
|
||||
public static void process(WordprocessingMLPackage wmlPackage) {
|
||||
Body body = wmlPackage.getMainDocumentPart().getJaxbElement().getBody();
|
||||
moveSectPr(body);
|
||||
}
|
||||
|
||||
private static void moveSectPr(Body body) {
|
||||
if (body == null || body.getContent().size() == 0) {
|
||||
log.warn("w:document/w:body null or empty");
|
||||
return;
|
||||
}
|
||||
Object o = body.getContent().get(0);
|
||||
if (o instanceof P) {
|
||||
SectPr sectPr = cutSectPr((P)o);
|
||||
if (sectPr != null) {
|
||||
pasteSectPr(body.getContent(), sectPr);
|
||||
log.info("Moved sectPr to new P");
|
||||
return;
|
||||
}
|
||||
} else if (o instanceof SdtElement) {
|
||||
Object o2 = ((SdtElement)o).getSdtContent().getContent().get(0);
|
||||
if (o2 != null && o2 instanceof P) {
|
||||
SectPr sectPr = cutSectPr((P)o2);
|
||||
if (sectPr != null) {
|
||||
pasteSectPr(((SdtElement)o).getSdtContent().getContent(), sectPr);
|
||||
log.info("Moved sectPr to new P inside content control");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
log.info("No need to move sectPr ");
|
||||
}
|
||||
|
||||
private static SectPr cutSectPr(P p) {
|
||||
if (p.getPPr() != null && p.getPPr().getSectPr() != null) {
|
||||
SectPr sectPr = p.getPPr().getSectPr();
|
||||
p.getPPr().setSectPr(null);
|
||||
return sectPr;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void pasteSectPr(List<Object> contentList, SectPr sectPr) {
|
||||
P p = new P();
|
||||
PPr ppr = Context.getWmlObjectFactory().createPPr();
|
||||
p.setPPr(ppr);
|
||||
ppr.setSectPr(sectPr);
|
||||
contentList.add(1, p);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
package org.docx4j.convert.out.common.preprocess;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.namespace.QName;
|
||||
import org.docx4j.TraversalUtil;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.jaxb.Context;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.utils.TraversalUtilVisitor;
|
||||
import org.docx4j.wml.CTSimpleField;
|
||||
import org.docx4j.wml.FldChar;
|
||||
import org.docx4j.wml.P;
|
||||
import org.docx4j.wml.R;
|
||||
import org.docx4j.wml.STFldCharType;
|
||||
import org.docx4j.wml.Text;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class FieldsCombiner {
|
||||
private static Logger log = LoggerFactory.getLogger(FieldsCombiner.class);
|
||||
|
||||
protected static final CombineVisitor COMBINE_VISITOR = new CombineVisitor();
|
||||
|
||||
public static void process(WordprocessingMLPackage wmlPackage) {
|
||||
log.info("starting");
|
||||
TraversalUtil.visit(wmlPackage, false, COMBINE_VISITOR);
|
||||
if (log.isDebugEnabled())
|
||||
log.debug(XmlUtils.marshaltoString(wmlPackage.getMainDocumentPart().getJaxbElement(), true, true));
|
||||
}
|
||||
|
||||
protected static class CombineVisitor extends TraversalUtilVisitor<P> {
|
||||
private static final QName _RInstrText_QNAME = new QName("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "instrText");
|
||||
|
||||
private static final int STATE_NONE = 0;
|
||||
|
||||
private static final int STATE_EXPECT_BEGIN = 1;
|
||||
|
||||
private static final int STATE_EXPECT_INSTR = 2;
|
||||
|
||||
private static final int STATE_EXPECT_RESULT = 4;
|
||||
|
||||
public void apply(P element) {
|
||||
processContent(element.getContent());
|
||||
}
|
||||
|
||||
protected void processContent(List<Object> pContent) {
|
||||
List<Object> pResult = null;
|
||||
boolean haveChanges = false;
|
||||
boolean inField = false;
|
||||
Object item = null;
|
||||
STFldCharType fldCharType = null;
|
||||
int level = 0;
|
||||
int state = 1;
|
||||
int markIdx = 0;
|
||||
List<Object> resultList = new ArrayList(2);
|
||||
StringBuilder instrTextBuffer = new StringBuilder(128);
|
||||
String tmpInstrText = null;
|
||||
if (pContent != null && !pContent.isEmpty()) {
|
||||
pResult = new ArrayList(pContent.size());
|
||||
for (int i = 0; i < pContent.size(); i++) {
|
||||
item = pContent.get(i);
|
||||
if (item instanceof R) {
|
||||
fldCharType = getFldCharType((R)item);
|
||||
if (fldCharType != null) {
|
||||
if (STFldCharType.BEGIN.equals(fldCharType)) {
|
||||
level++;
|
||||
state = 2;
|
||||
if (markIdx < i) {
|
||||
copyItems(pContent, markIdx, i, pResult);
|
||||
instrTextBuffer.setLength(0);
|
||||
resultList.clear();
|
||||
}
|
||||
markIdx = i;
|
||||
} else if (STFldCharType.SEPARATE.equals(fldCharType)) {
|
||||
state = 4;
|
||||
} else if (STFldCharType.END.equals(fldCharType) &&
|
||||
level > 0) {
|
||||
state = 1;
|
||||
if (!resultList.isEmpty() && instrTextBuffer.length() > 0) {
|
||||
pResult.add(createFldSimple(instrTextBuffer.toString(), resultList));
|
||||
haveChanges = true;
|
||||
markIdx = i + 1;
|
||||
}
|
||||
instrTextBuffer.setLength(0);
|
||||
resultList.clear();
|
||||
level--;
|
||||
}
|
||||
} else {
|
||||
switch (state) {
|
||||
case 2:
|
||||
tmpInstrText = getInstrText((R)item);
|
||||
if (tmpInstrText != null)
|
||||
instrTextBuffer.append(tmpInstrText);
|
||||
break;
|
||||
case 4:
|
||||
resultList.add(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (item instanceof JAXBElement && ((JAXBElement)item).getValue() instanceof CTSimpleField) {
|
||||
if (markIdx < i)
|
||||
copyItems(pContent, markIdx, i, pResult);
|
||||
pResult.add(item);
|
||||
instrTextBuffer.setLength(0);
|
||||
resultList.clear();
|
||||
markIdx = i + 1;
|
||||
state = 1;
|
||||
} else if (item instanceof JAXBElement && ((JAXBElement)item).getValue() instanceof P.Hyperlink) {
|
||||
processContent(((P.Hyperlink)((JAXBElement)item).getValue()).getContent());
|
||||
}
|
||||
}
|
||||
if (haveChanges) {
|
||||
if (markIdx < pContent.size())
|
||||
copyItems(pContent, markIdx, pContent.size(), pResult);
|
||||
pContent.clear();
|
||||
pContent.addAll(pResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getInstrText(R run) {
|
||||
List<Object> rContent = run.getContent();
|
||||
Object item = null;
|
||||
Text text = null;
|
||||
for (int i = 0; i < rContent.size(); i++) {
|
||||
item = rContent.get(i);
|
||||
if (item instanceof JAXBElement && ((JAXBElement)item).getName().equals(_RInstrText_QNAME)) {
|
||||
text = (Text)((JAXBElement)item).getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (text != null) ? text.getValue() : null;
|
||||
}
|
||||
|
||||
private Object createFldSimple(String instrText, List<Object> resultList) {
|
||||
CTSimpleField fldSimple = Context.getWmlObjectFactory().createCTSimpleField();
|
||||
fldSimple.setInstr(instrText);
|
||||
if (resultList != null && !resultList.isEmpty())
|
||||
fldSimple.getContent().addAll(resultList);
|
||||
return fldSimple;
|
||||
}
|
||||
|
||||
private void copyItems(List<Object> source, int startIdx, int endIdx, List<Object> destination) {
|
||||
for (int i = startIdx; i < endIdx; i++)
|
||||
destination.add(source.get(i));
|
||||
}
|
||||
|
||||
private STFldCharType getFldCharType(R r) {
|
||||
STFldCharType ret = null;
|
||||
List<Object> rContent = r.getContent();
|
||||
Object item = null;
|
||||
if (rContent != null && !rContent.isEmpty())
|
||||
for (int i = 0; i < rContent.size(); i++) {
|
||||
item = XmlUtils.unwrap(rContent.get(i));
|
||||
if (item instanceof FldChar) {
|
||||
ret = ((FldChar)item).getFldCharType();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package org.docx4j.convert.out.common.preprocess;
|
||||
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.wml.Body;
|
||||
import org.docx4j.wml.BooleanDefaultTrue;
|
||||
import org.docx4j.wml.P;
|
||||
import org.docx4j.wml.PPr;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class FopWorkaroundDisablePageBreakOnFirstParagraph {
|
||||
private static Logger log = LoggerFactory.getLogger(FopWorkaroundDisablePageBreakOnFirstParagraph.class);
|
||||
|
||||
public static void process(WordprocessingMLPackage wmlPackage) {
|
||||
Body body = wmlPackage.getMainDocumentPart().getJaxbElement().getBody();
|
||||
if (body == null || body.getContent().size() == 0) {
|
||||
log.warn("w:document/w:body null or empty");
|
||||
return;
|
||||
}
|
||||
Object o = body.getContent().get(0);
|
||||
if (o instanceof P && ((P)o).getPPr() != null) {
|
||||
PPr pPr = ((P)o).getPPr();
|
||||
BooleanDefaultTrue val = new BooleanDefaultTrue();
|
||||
val.setVal(Boolean.FALSE);
|
||||
pPr.setPageBreakBefore(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
package org.docx4j.convert.out.common.preprocess;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.docx4j.jaxb.Context;
|
||||
import org.docx4j.model.PropertyResolver;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.wml.BooleanDefaultTrue;
|
||||
import org.docx4j.wml.P;
|
||||
import org.docx4j.wml.PPr;
|
||||
import org.docx4j.wml.SdtElement;
|
||||
|
||||
public class FopWorkaroundReplacePageBreakInEachList {
|
||||
private WordprocessingMLPackage wmlPackage;
|
||||
|
||||
public static void process(WordprocessingMLPackage wmlPackage) {
|
||||
FopWorkaroundReplacePageBreakInEachList worker = new FopWorkaroundReplacePageBreakInEachList(wmlPackage);
|
||||
worker.process();
|
||||
}
|
||||
|
||||
private FopWorkaroundReplacePageBreakInEachList(WordprocessingMLPackage wmlPackage) {
|
||||
this.wmlPackage = wmlPackage;
|
||||
}
|
||||
|
||||
private PropertyResolver propertyResolver = null;
|
||||
|
||||
private void process() {
|
||||
this.propertyResolver = this.wmlPackage.getMainDocumentPart().getPropertyResolver();
|
||||
List<Object> newContent = process(this.wmlPackage.getMainDocumentPart().getContent());
|
||||
this.wmlPackage.getMainDocumentPart().getJaxbElement().getBody().getContent().clear();
|
||||
this.wmlPackage.getMainDocumentPart().getJaxbElement().getBody().getContent().addAll(newContent);
|
||||
}
|
||||
|
||||
private List process(List contentIn) {
|
||||
List<Object> newContent = new ArrayList();
|
||||
boolean inList = false;
|
||||
for (Object o : (Iterable<Object>)contentIn) {
|
||||
if (o instanceof P) {
|
||||
P p = (P)o;
|
||||
PPr effPPr = getEffectivePPr(p);
|
||||
if (isListItem(effPPr)) {
|
||||
inList = true;
|
||||
if (hasBreakBefore(effPPr)) {
|
||||
P newP = new P();
|
||||
newP.setPPr(new PPr());
|
||||
newP.getPPr().setPageBreakBefore(new BooleanDefaultTrue());
|
||||
newContent.add(newP);
|
||||
PPr pPr = p.getPPr();
|
||||
if (pPr == null) {
|
||||
pPr = Context.getWmlObjectFactory().createPPr();
|
||||
p.setPPr(pPr);
|
||||
}
|
||||
BooleanDefaultTrue val = new BooleanDefaultTrue();
|
||||
val.setVal(Boolean.FALSE);
|
||||
pPr.setPageBreakBefore(val);
|
||||
}
|
||||
}
|
||||
newContent.add(o);
|
||||
continue;
|
||||
}
|
||||
if (o instanceof SdtElement) {
|
||||
newContent.add(o);
|
||||
SdtElement sdt = (SdtElement)o;
|
||||
List<Object> recursiveL = process(sdt.getSdtContent().getContent());
|
||||
sdt.getSdtContent().getContent().clear();
|
||||
sdt.getSdtContent().getContent().addAll(recursiveL);
|
||||
continue;
|
||||
}
|
||||
newContent.add(o);
|
||||
}
|
||||
return newContent;
|
||||
}
|
||||
|
||||
private PPr getEffectivePPr(P p) {
|
||||
PPr pPrDirect = p.getPPr();
|
||||
return this.propertyResolver.getEffectivePPr(pPrDirect);
|
||||
}
|
||||
|
||||
private boolean isListItem(PPr pPr) {
|
||||
return (pPr != null && pPr.getNumPr() != null);
|
||||
}
|
||||
|
||||
private static boolean hasBreakBefore(PPr pPr) {
|
||||
return (pPr != null && pPr.getPageBreakBefore() != null && pPr.getPageBreakBefore().isVal());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package org.docx4j.convert.out.common.preprocess;
|
||||
|
||||
import java.util.List;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.wml.Body;
|
||||
import org.docx4j.wml.BooleanDefaultTrue;
|
||||
import org.docx4j.wml.Br;
|
||||
import org.docx4j.wml.P;
|
||||
import org.docx4j.wml.PPr;
|
||||
import org.docx4j.wml.R;
|
||||
import org.docx4j.wml.STBrType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class PageBreak {
|
||||
private static Logger log = LoggerFactory.getLogger(PageBreak.class);
|
||||
|
||||
public static void process(WordprocessingMLPackage wmlPackage) {
|
||||
Body body = wmlPackage.getMainDocumentPart().getJaxbElement().getBody();
|
||||
movePageBreaks(body);
|
||||
}
|
||||
|
||||
private static void movePageBreaks(Body body) {
|
||||
List<Object> elts = body.getContent();
|
||||
for (Object o : elts) {
|
||||
if (o instanceof P)
|
||||
updateParagraph((P)o);
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateParagraph(P paragraph) {
|
||||
boolean containsPageBreak = checkPageBreak(paragraph.getContent());
|
||||
if (containsPageBreak) {
|
||||
if (paragraph.getPPr() == null)
|
||||
paragraph.setPPr(new PPr());
|
||||
paragraph.getPPr().setPageBreakBefore(new BooleanDefaultTrue());
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean checkPageBreak(List<Object> content) {
|
||||
int foundIdx = -1;
|
||||
Object ce = null;
|
||||
if (content != null && !content.isEmpty()) {
|
||||
for (int i = 0; foundIdx == -1 && i < content.size(); i++) {
|
||||
ce = content.get(i);
|
||||
if (ce instanceof R) {
|
||||
if (checkPageBreak(((R)ce).getContent()))
|
||||
if (((R)ce).getContent() == null || ((R)ce).getContent().isEmpty()) {
|
||||
foundIdx = i;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else if (ce instanceof Br &&
|
||||
STBrType.PAGE.equals(((Br)ce).getType())) {
|
||||
foundIdx = i;
|
||||
}
|
||||
}
|
||||
if (foundIdx > -1)
|
||||
content.remove(foundIdx);
|
||||
}
|
||||
return (foundIdx > -1);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
package org.docx4j.convert.out.common.preprocess;
|
||||
|
||||
import org.docx4j.wml.CTPageNumber;
|
||||
import org.docx4j.wml.NumberFormat;
|
||||
import org.docx4j.wml.SectPr;
|
||||
|
||||
public class PageNumberInformation {
|
||||
protected String defaultNumberFormat = null;
|
||||
|
||||
protected boolean pagePresent = false;
|
||||
|
||||
protected String pageFormat = null;
|
||||
|
||||
protected int pageStart = -1;
|
||||
|
||||
protected boolean numpagesPresent = false;
|
||||
|
||||
protected String numpagesFormat = null;
|
||||
|
||||
protected boolean sectionpagesPresent = false;
|
||||
|
||||
protected String sectionpagesFormat = null;
|
||||
|
||||
public PageNumberInformation(SectPr sectPr) {
|
||||
CTPageNumber pageNumber = (sectPr != null) ? sectPr.getPgNumType() : null;
|
||||
NumberFormat numberFormat = null;
|
||||
if (pageNumber != null) {
|
||||
if (pageNumber.getFmt() != null)
|
||||
this.defaultNumberFormat = pageNumber.getFmt().value();
|
||||
if (pageNumber.getStart() != null)
|
||||
this.pageStart = pageNumber.getStart().intValue();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPagePresent() {
|
||||
return this.pagePresent;
|
||||
}
|
||||
|
||||
public void setPagePresent(boolean pagePresent) {
|
||||
this.pagePresent = pagePresent;
|
||||
}
|
||||
|
||||
public boolean hasPageFormat() {
|
||||
return (this.pageFormat != null);
|
||||
}
|
||||
|
||||
public String getPageFormat() {
|
||||
return hasPageFormat() ? this.pageFormat : this.defaultNumberFormat;
|
||||
}
|
||||
|
||||
public void setPageFormat(String pageFormat) {
|
||||
this.pageFormat = pageFormat;
|
||||
}
|
||||
|
||||
public boolean hasPageStart() {
|
||||
return (this.pageStart != -1);
|
||||
}
|
||||
|
||||
public int getPageStart() {
|
||||
return this.pageStart;
|
||||
}
|
||||
|
||||
public void setPageStart(int pageStart) {
|
||||
this.pageStart = pageStart;
|
||||
}
|
||||
|
||||
public boolean isNumpagesPresent() {
|
||||
return this.numpagesPresent;
|
||||
}
|
||||
|
||||
public void setNumpagesPresent(boolean numpagesPresent) {
|
||||
this.numpagesPresent = numpagesPresent;
|
||||
}
|
||||
|
||||
public boolean hasNumpagesFormat() {
|
||||
return (this.numpagesFormat != null);
|
||||
}
|
||||
|
||||
public String getNumpagesFormat() {
|
||||
return hasNumpagesFormat() ? this.numpagesFormat : this.defaultNumberFormat;
|
||||
}
|
||||
|
||||
public void setNumpagesFormat(String numpagesFormat) {
|
||||
this.numpagesFormat = numpagesFormat;
|
||||
}
|
||||
|
||||
public boolean isSectionpagesPresent() {
|
||||
return this.sectionpagesPresent;
|
||||
}
|
||||
|
||||
public void setSectionpagesPresent(boolean sectionpagesPresent) {
|
||||
this.sectionpagesPresent = sectionpagesPresent;
|
||||
}
|
||||
|
||||
public boolean hasSectionpagesFormat() {
|
||||
return (this.sectionpagesFormat != null);
|
||||
}
|
||||
|
||||
public String getSectionpagesFormat() {
|
||||
return hasSectionpagesFormat() ? this.sectionpagesFormat : this.defaultNumberFormat;
|
||||
}
|
||||
|
||||
public void setSectionpagesFormat(String sectionpagesFormat) {
|
||||
this.sectionpagesFormat = sectionpagesFormat;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
this.defaultNumberFormat = null;
|
||||
this.pagePresent = false;
|
||||
this.pageFormat = null;
|
||||
this.pageStart = -1;
|
||||
this.numpagesPresent = false;
|
||||
this.numpagesFormat = null;
|
||||
this.sectionpagesPresent = false;
|
||||
this.sectionpagesFormat = null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
package org.docx4j.convert.out.common.preprocess;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.docx4j.TraversalUtil;
|
||||
import org.docx4j.convert.out.common.ConversionSectionWrapper;
|
||||
import org.docx4j.model.fields.FldSimpleModel;
|
||||
import org.docx4j.model.fields.FormattingSwitchHelper;
|
||||
import org.docx4j.model.structure.HeaderFooterPolicy;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.FooterPart;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.HeaderPart;
|
||||
import org.docx4j.utils.TraversalUtilVisitor;
|
||||
import org.docx4j.wml.CTSimpleField;
|
||||
|
||||
public class PageNumberInformationCollector {
|
||||
public static PageNumberInformation process(ConversionSectionWrapper sectionWrapper, boolean dummyPageNumbering) {
|
||||
PageNumberInformation ret = new PageNumberInformation(sectionWrapper.getSectPr());
|
||||
FieldVisitor fldVisitor = null;
|
||||
HeaderFooterPolicy headerFooterPolicy = sectionWrapper.getHeaderFooterPolicy();
|
||||
if (!dummyPageNumbering) {
|
||||
fldVisitor = new FieldVisitor(ret);
|
||||
TraversalUtil.visit(sectionWrapper.getContent(), fldVisitor);
|
||||
process(headerFooterPolicy.getFirstHeader(), fldVisitor);
|
||||
process(headerFooterPolicy.getFirstFooter(), fldVisitor);
|
||||
process(headerFooterPolicy.getDefaultHeader(), fldVisitor);
|
||||
process(headerFooterPolicy.getDefaultFooter(), fldVisitor);
|
||||
process(headerFooterPolicy.getEvenHeader(), fldVisitor);
|
||||
process(headerFooterPolicy.getEvenFooter(), fldVisitor);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected static void process(FooterPart footer, FieldVisitor fldVisitor) {
|
||||
if (footer != null && !footer.getContent().isEmpty())
|
||||
TraversalUtil.visit(footer.getContent(), fldVisitor);
|
||||
}
|
||||
|
||||
protected static void process(HeaderPart header, FieldVisitor fldVisitor) {
|
||||
if (header != null && !header.getContent().isEmpty())
|
||||
TraversalUtil.visit(header.getContent(), fldVisitor);
|
||||
}
|
||||
|
||||
protected static class FieldVisitor extends TraversalUtilVisitor<CTSimpleField> {
|
||||
private static final Object PAGE_FIELD_TYPE = "PAGE";
|
||||
|
||||
private static final Object NUMPAGES_FIELD_TYPE = "NUMPAGES";
|
||||
|
||||
private static final Object SECTIONPAGES_FIELD_TYPE = "SECTIONPAGES";
|
||||
|
||||
protected PageNumberInformation results = null;
|
||||
|
||||
protected FldSimpleModel fldSimpleModel = new FldSimpleModel();
|
||||
|
||||
public FieldVisitor(PageNumberInformation results) {
|
||||
this.results = results;
|
||||
}
|
||||
|
||||
public void apply(CTSimpleField element) {
|
||||
String instr = element.getInstr();
|
||||
String fieldType = FormattingSwitchHelper.getFldSimpleName(instr);
|
||||
if (PAGE_FIELD_TYPE.equals(fieldType)) {
|
||||
this.results.setPagePresent(true);
|
||||
this.results.setPageFormat(extractFormat(instr));
|
||||
} else if (NUMPAGES_FIELD_TYPE.equals(fieldType)) {
|
||||
this.results.setNumpagesPresent(true);
|
||||
this.results.setNumpagesFormat(extractFormat(instr));
|
||||
} else if (SECTIONPAGES_FIELD_TYPE.equals(fieldType)) {
|
||||
this.results.setSectionpagesPresent(true);
|
||||
this.results.setSectionpagesFormat(extractFormat(instr));
|
||||
}
|
||||
}
|
||||
|
||||
protected String extractFormat(String instr) {
|
||||
String ret = null;
|
||||
try {
|
||||
this.fldSimpleModel.build(instr);
|
||||
return FormattingSwitchHelper.findFirstSwitchValue("\\*", this.fldSimpleModel.getFldParameters(), true);
|
||||
} catch (TransformerException e) {
|
||||
ret = null;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,294 @@
|
|||
package org.docx4j.convert.out.common.preprocess;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.docx4j.TraversalUtil;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.jaxb.Context;
|
||||
import org.docx4j.model.PropertyResolver;
|
||||
import org.docx4j.model.styles.StyleUtil;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.DocumentSettingsPart;
|
||||
import org.docx4j.wml.CTCompatSetting;
|
||||
import org.docx4j.wml.HpsMeasure;
|
||||
import org.docx4j.wml.Jc;
|
||||
import org.docx4j.wml.JcEnumeration;
|
||||
import org.docx4j.wml.P;
|
||||
import org.docx4j.wml.PPr;
|
||||
import org.docx4j.wml.PPrBase;
|
||||
import org.docx4j.wml.RPr;
|
||||
import org.docx4j.wml.SdtBlock;
|
||||
import org.docx4j.wml.Style;
|
||||
import org.docx4j.wml.Styles;
|
||||
import org.docx4j.wml.Tbl;
|
||||
import org.docx4j.wml.TblPr;
|
||||
import org.jvnet.jaxb2_commons.ppp.Child;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ParagraphStylesInTableFix {
|
||||
protected static Logger log = LoggerFactory.getLogger(ParagraphStylesInTableFix.class);
|
||||
|
||||
private static final CTCompatSetting defaultSetting = Context.getWmlObjectFactory().createCTCompatSetting();
|
||||
|
||||
static {
|
||||
defaultSetting.setVal("0");
|
||||
}
|
||||
|
||||
public static void process(WordprocessingMLPackage wmlPackage) {
|
||||
Throwable t = new Throwable();
|
||||
StackTraceElement[] trace = t.getStackTrace();
|
||||
for (int i = 0; i < trace.length; i++) {
|
||||
if (trace[i].getClassName().contains("FOPAreaTreeHelper"))
|
||||
return;
|
||||
}
|
||||
StyleRenamer styleRenamer = new StyleRenamer();
|
||||
try {
|
||||
DocumentSettingsPart dsp = wmlPackage.getMainDocumentPart().getDocumentSettingsPart();
|
||||
if (dsp == null) {
|
||||
dsp = new DocumentSettingsPart();
|
||||
wmlPackage.getMainDocumentPart().addTargetPart(dsp);
|
||||
dsp.setContents(Context.getWmlObjectFactory().createCTSettings());
|
||||
} else {
|
||||
styleRenamer.overrideTableStyleFontSizeAndJustification = dsp.getWordCompatSetting("overrideTableStyleFontSizeAndJustification");
|
||||
if (styleRenamer.overrideTableStyleFontSizeAndJustification == null)
|
||||
styleRenamer.overrideTableStyleFontSizeAndJustification = defaultSetting;
|
||||
}
|
||||
dsp.setWordCompatSetting("overrideTableStyleFontSizeAndJustification", "1");
|
||||
} catch (Docx4JException e) {
|
||||
log.error(e.getMessage(), (Throwable)e);
|
||||
}
|
||||
try {
|
||||
styleRenamer.setDefaultParagraphStyle(wmlPackage.getMainDocumentPart().getStyleDefinitionsPart().getDefaultParagraphStyle().getStyleId());
|
||||
} catch (NullPointerException npe) {
|
||||
log.warn("No default paragraph style!!");
|
||||
}
|
||||
Style defaultTableStyle = wmlPackage.getMainDocumentPart().getStyleDefinitionsPart().getDefaultTableStyle();
|
||||
if (defaultTableStyle != null)
|
||||
styleRenamer.setDefaultTableStyle(defaultTableStyle);
|
||||
Styles styles = wmlPackage.getMainDocumentPart().getStyleDefinitionsPart().getJaxbElement();
|
||||
styleRenamer.propertyResolver = wmlPackage.getMainDocumentPart().getPropertyResolver();
|
||||
styleRenamer.setStyles(styles);
|
||||
try {
|
||||
new TraversalUtil(wmlPackage.getMainDocumentPart().getContents(), styleRenamer);
|
||||
} catch (Docx4JException e) {
|
||||
log.error(e.getMessage(), (Throwable)e);
|
||||
}
|
||||
}
|
||||
|
||||
public static class StyleRenamer extends TraversalUtil.CallbackImpl {
|
||||
protected static Logger log = LoggerFactory.getLogger(StyleRenamer.class);
|
||||
|
||||
CTCompatSetting overrideTableStyleFontSizeAndJustification = ParagraphStylesInTableFix.defaultSetting;
|
||||
|
||||
private PropertyResolver propertyResolver;
|
||||
|
||||
private String defaultParagraphStyle;
|
||||
|
||||
private Style defaultTableStyle;
|
||||
|
||||
public void setDefaultParagraphStyle(String defaultParagraphStyle) {
|
||||
log.debug(defaultParagraphStyle);
|
||||
this.defaultParagraphStyle = defaultParagraphStyle;
|
||||
}
|
||||
|
||||
public void setDefaultTableStyle(Style defaultTableStyle) {
|
||||
this.defaultTableStyle = defaultTableStyle;
|
||||
}
|
||||
|
||||
private LinkedList<Tbl> tblStack = new LinkedList<Tbl>();
|
||||
|
||||
private Map<String, Style> allStyles = null;
|
||||
|
||||
public void setStyles(Styles newStyles) {
|
||||
this.allStyles = new HashMap<String, Style>();
|
||||
for (Style s : newStyles.getStyle())
|
||||
this.allStyles.put(s.getStyleId(), s);
|
||||
}
|
||||
|
||||
private Set<String> cellPStyles = new HashSet<String>();
|
||||
|
||||
private boolean isFalse(CTCompatSetting overrideTableStyleFontSizeAndJustification) {
|
||||
return (overrideTableStyleFontSizeAndJustification.getVal().equals("0") || overrideTableStyleFontSizeAndJustification.getVal().toLowerCase().equals("false") || overrideTableStyleFontSizeAndJustification.getVal().toLowerCase().equals("no"));
|
||||
}
|
||||
|
||||
private String getCellPStyle(String styleVal, boolean pStyleIsDefault) {
|
||||
Style expressStyle = this.allStyles.get(styleVal);
|
||||
Jc expressStyleJc = (expressStyle.getPPr() == null) ? null : expressStyle.getPPr().getJc();
|
||||
HpsMeasure expressStyleFontSize = null;
|
||||
if (expressStyle.getRPr() != null)
|
||||
expressStyleFontSize = expressStyle.getRPr().getSz();
|
||||
PPr effectivePPr = this.propertyResolver.getEffectivePPr(styleVal);
|
||||
Jc effectiveJc = effectivePPr.getJc();
|
||||
RPr effectiveRPr = this.propertyResolver.getEffectiveRPr(styleVal);
|
||||
HpsMeasure effectiveFontSize = null;
|
||||
if (effectiveRPr != null)
|
||||
effectiveFontSize = effectiveRPr.getSz();
|
||||
String tableStyle = null;
|
||||
TblPr tblPr = this.tblStack.peek().getTblPr();
|
||||
if (tblPr != null && tblPr.getTblStyle() != null) {
|
||||
tableStyle = tblPr.getTblStyle().getVal();
|
||||
} else {
|
||||
if (this.defaultTableStyle == null) {
|
||||
log.warn("No default table style defined in docx Style Definitions part");
|
||||
return null;
|
||||
}
|
||||
if (this.defaultTableStyle.getName() != null && this.defaultTableStyle.getName().getVal() != null && this.defaultTableStyle.getName().getVal().equals("Normal Table")) {
|
||||
log.debug("Ignoring style with name 'Normal Table' (mimicking Word)");
|
||||
return null;
|
||||
}
|
||||
tableStyle = this.defaultTableStyle.getStyleId();
|
||||
if (tableStyle == null) {
|
||||
log.error("Default table style has no ID!");
|
||||
log.error(XmlUtils.marshaltoString(tableStyle));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
String resultStyleID = styleVal + "-" + tableStyle;
|
||||
if (!tableStyle.endsWith("-BR"))
|
||||
resultStyleID = resultStyleID + "-BR";
|
||||
if (this.cellPStyles.contains(resultStyleID))
|
||||
return resultStyleID;
|
||||
List<Style> hierarchy = new ArrayList<Style>();
|
||||
Style basedOn = null;
|
||||
String currentStyle = styleVal;
|
||||
do {
|
||||
Style thisStyle = this.allStyles.get(currentStyle);
|
||||
hierarchy.add(thisStyle);
|
||||
if (thisStyle.getBasedOn() != null) {
|
||||
currentStyle = thisStyle.getBasedOn().getVal();
|
||||
} else {
|
||||
currentStyle = null;
|
||||
}
|
||||
} while (currentStyle != null);
|
||||
Style newStyle = Context.getWmlObjectFactory().createStyle();
|
||||
newStyle.setType("paragraph");
|
||||
Style styleToApply = hierarchy.get(hierarchy.size() - 1);
|
||||
log.debug("DocDefault");
|
||||
log.debug(XmlUtils.marshaltoString(styleToApply, true, true));
|
||||
StyleUtil.apply(styleToApply, newStyle);
|
||||
log.debug("Result");
|
||||
log.debug(XmlUtils.marshaltoString(newStyle, true, true));
|
||||
Style tableStyleContrib = null;
|
||||
List<Style> tblStyles = new ArrayList<Style>();
|
||||
if (tableStyle != null) {
|
||||
currentStyle = tableStyle;
|
||||
do {
|
||||
log.debug(currentStyle);
|
||||
Style thisStyle = this.allStyles.get(currentStyle);
|
||||
if (thisStyle.getName().getVal().equals("Normal Table"))
|
||||
break;
|
||||
tblStyles.add(thisStyle);
|
||||
if (thisStyle.getBasedOn() != null) {
|
||||
currentStyle = thisStyle.getBasedOn().getVal();
|
||||
} else {
|
||||
currentStyle = null;
|
||||
}
|
||||
} while (currentStyle != null);
|
||||
for (int j = tblStyles.size() - 1; j >= 0; j--) {
|
||||
styleToApply = tblStyles.get(j);
|
||||
log.debug("Applying " + styleToApply.getStyleId() + "\n" + XmlUtils.marshaltoString(styleToApply, true, true));
|
||||
tableStyleContrib = StyleUtil.apply(styleToApply, tableStyleContrib);
|
||||
log.debug(XmlUtils.marshaltoString(tableStyleContrib, true, true));
|
||||
}
|
||||
}
|
||||
if (tableStyleContrib == null)
|
||||
tableStyleContrib = Context.getWmlObjectFactory().createStyle();
|
||||
Jc tableStyleJc = (tableStyleContrib.getPPr() == null) ? null : tableStyleContrib.getPPr().getJc();
|
||||
HpsMeasure tableStyleFontSize = null;
|
||||
if (tableStyleContrib.getRPr() != null)
|
||||
tableStyleFontSize = tableStyleContrib.getRPr().getSz();
|
||||
newStyle.setPPr(StyleUtil.apply(tableStyleContrib.getPPr(), newStyle.getPPr()));
|
||||
newStyle.setRPr(StyleUtil.apply(tableStyleContrib.getRPr(), newStyle.getRPr()));
|
||||
log.debug(XmlUtils.marshaltoString(newStyle, true, true));
|
||||
for (int i = hierarchy.size() - 2; i >= 0; i--) {
|
||||
styleToApply = hierarchy.get(i);
|
||||
log.debug("Applying " + styleToApply.getStyleId() + "\n" + XmlUtils.marshaltoString(styleToApply, true, true));
|
||||
StyleUtil.apply(styleToApply, newStyle);
|
||||
log.debug("Result: \n" + XmlUtils.marshaltoString(newStyle, true, true));
|
||||
}
|
||||
if (isFalse(this.overrideTableStyleFontSizeAndJustification)) {
|
||||
log.info("giving TableStyleFontSizeAndJustification primacy, as per this docx w:compatSetting");
|
||||
if (styleVal.equals(this.defaultParagraphStyle) || expressStyleFontSize == null)
|
||||
if (tableStyleFontSize != null)
|
||||
if (effectiveFontSize != null && effectiveFontSize.getVal().intValue() == 24)
|
||||
newStyle.getRPr().setSz(tableStyleFontSize);
|
||||
if (styleVal.equals(this.defaultParagraphStyle) || expressStyleJc == null)
|
||||
if (tableStyleJc != null)
|
||||
if (effectiveJc != null && effectiveJc.getVal().equals(JcEnumeration.LEFT))
|
||||
newStyle.getPPr().setJc(tableStyleJc);
|
||||
}
|
||||
Style.Name name = Context.getWmlObjectFactory().createStyleName();
|
||||
name.setVal(resultStyleID);
|
||||
newStyle.setName(name);
|
||||
newStyle.setStyleId(resultStyleID);
|
||||
this.cellPStyles.add(resultStyleID);
|
||||
this.propertyResolver.activateStyle(newStyle);
|
||||
log.debug(XmlUtils.marshaltoString(newStyle, true, true));
|
||||
return resultStyleID;
|
||||
}
|
||||
|
||||
public List<Object> apply(Object o) {
|
||||
if (o instanceof P) {
|
||||
P p = (P)o;
|
||||
if (p.getPPr() == null)
|
||||
p.setPPr(Context.getWmlObjectFactory().createPPr());
|
||||
if (p.getPPr().getPStyle() == null) {
|
||||
String newStyle = this.defaultParagraphStyle;
|
||||
p.getPPr().setPStyle(Context.getWmlObjectFactory().createPPrBasePStyle());
|
||||
if (this.tblStack.size() == 0) {
|
||||
p.getPPr().getPStyle().setVal(newStyle);
|
||||
} else {
|
||||
String resultStyle = getCellPStyle(newStyle, true);
|
||||
if (resultStyle == null) {
|
||||
p.getPPr().getPStyle().setVal(newStyle);
|
||||
} else {
|
||||
p.getPPr().getPStyle().setVal(resultStyle);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PPrBase.PStyle pstyle = p.getPPr().getPStyle();
|
||||
String styleVal = pstyle.getVal();
|
||||
if (styleVal != null &&
|
||||
this.tblStack.size() > 0) {
|
||||
log.debug("Fixing " + pstyle.getVal());
|
||||
String newStyle = getCellPStyle(styleVal, styleVal.equals(this.defaultParagraphStyle));
|
||||
if (newStyle == null) {
|
||||
log.debug("getCellPStyle returned null, so leave as is");
|
||||
} else {
|
||||
p.getPPr().getPStyle().setVal(newStyle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void walkJAXBElements(Object parent) {
|
||||
List<Object> children = getChildren(parent);
|
||||
if (children != null)
|
||||
for (Object o : children) {
|
||||
o = XmlUtils.unwrap(o);
|
||||
if (o instanceof Child)
|
||||
if (parent instanceof SdtBlock) {
|
||||
((Child)o).setParent(((SdtBlock)parent).getSdtContent());
|
||||
} else {
|
||||
((Child)o).setParent(parent);
|
||||
}
|
||||
apply(o);
|
||||
if (o instanceof Tbl)
|
||||
this.tblStack.push((Tbl)o);
|
||||
if (shouldTraverse(o))
|
||||
walkJAXBElements(o);
|
||||
if (o instanceof Tbl)
|
||||
this.tblStack.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
package org.docx4j.convert.out.common.preprocess;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.model.datastorage.CustomXmlDataStorage;
|
||||
import org.docx4j.openpackaging.Base;
|
||||
import org.docx4j.openpackaging.contenttype.ContentType;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.openpackaging.packages.OpcPackage;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.openpackaging.parts.CustomXmlDataStoragePart;
|
||||
import org.docx4j.openpackaging.parts.JaxbXmlPart;
|
||||
import org.docx4j.openpackaging.parts.Part;
|
||||
import org.docx4j.openpackaging.parts.PartName;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPart;
|
||||
import org.docx4j.openpackaging.parts.XmlPart;
|
||||
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
|
||||
import org.docx4j.relationships.Relationship;
|
||||
import org.docx4j.relationships.Relationships;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
public class PartialDeepCopy {
|
||||
protected static Logger log = LoggerFactory.getLogger(PartialDeepCopy.class);
|
||||
|
||||
public static OpcPackage process(OpcPackage opcPackage, Set<String> relationshipTypes) throws Docx4JException {
|
||||
OpcPackage ret = null;
|
||||
RelationshipsPart relPart = null;
|
||||
if (opcPackage != null)
|
||||
if (relationshipTypes != null && relationshipTypes.isEmpty()) {
|
||||
ret = opcPackage;
|
||||
} else {
|
||||
ret = createPackage(opcPackage);
|
||||
if (ret == null)
|
||||
log.error("createPackage returned null!");
|
||||
deepCopyRelationships(ret, opcPackage, ret, relationshipTypes);
|
||||
if (opcPackage instanceof WordprocessingMLPackage)
|
||||
try {
|
||||
((WordprocessingMLPackage)ret).setFontMapper(((WordprocessingMLPackage)opcPackage).getFontMapper(), false);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), (Throwable)e);
|
||||
throw new Docx4JException("Error setting font mapper on copy", e);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected static OpcPackage createPackage(OpcPackage opcPackage) throws Docx4JException {
|
||||
OpcPackage ret = null;
|
||||
try {
|
||||
ret = (OpcPackage)opcPackage.getClass().newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
throw new Docx4JException("InstantiationException duplicating package", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new Docx4JException("IllegalAccessException duplicating package", e);
|
||||
}
|
||||
ret.setContentType(new ContentType(opcPackage.getContentType()));
|
||||
ret.setPartName(opcPackage.getPartName());
|
||||
ret.setContentTypeManager(opcPackage.getContentTypeManager());
|
||||
ret.getCustomXmlDataStorageParts().putAll(opcPackage.getCustomXmlDataStorageParts());
|
||||
ret.setPartShortcut(opcPackage.getDocPropsCorePart(), "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties");
|
||||
ret.setPartShortcut(opcPackage.getDocPropsCustomPart(), "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties");
|
||||
ret.setPartShortcut(opcPackage.getDocPropsExtendedPart(), "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties");
|
||||
ret.getExternalResources().putAll(opcPackage.getExternalResources());
|
||||
ret.setSourcePartStore(opcPackage.getSourcePartStore());
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected static void deepCopyRelationships(OpcPackage opcPackage, Base sourcePart, Base targetPart, Set<String> relationshipTypes) throws Docx4JException {
|
||||
RelationshipsPart sourceRelationshipsPart = sourcePart.getRelationshipsPart(false);
|
||||
Relationships sourceRelationships = (sourceRelationshipsPart != null) ? sourceRelationshipsPart.getRelationships() : null;
|
||||
List<Relationship> sourceRelationshipList = (sourceRelationships != null) ? sourceRelationships.getRelationship() : null;
|
||||
RelationshipsPart targetRelationshipsPart = null;
|
||||
Relationships targetRelationships = null;
|
||||
Relationship sourceRelationship = null;
|
||||
Relationship targetRelationship = null;
|
||||
Part sourceChild = null;
|
||||
Part targetChild = null;
|
||||
if (sourceRelationshipList != null && !sourceRelationshipList.isEmpty()) {
|
||||
targetRelationshipsPart = targetPart.getRelationshipsPart();
|
||||
targetRelationships = targetRelationshipsPart.getRelationships();
|
||||
for (int i = 0; i < sourceRelationshipList.size(); i++) {
|
||||
sourceRelationship = sourceRelationshipList.get(i);
|
||||
targetRelationships.getRelationship().add(sourceRelationship);
|
||||
if (sourceRelationship.getTargetMode() == null || !"external".equals(sourceRelationship.getTargetMode().toLowerCase())) {
|
||||
sourceChild = sourceRelationshipsPart.getPart(sourceRelationship);
|
||||
targetChild = deepCopyPart(opcPackage, targetPart, sourceChild, relationshipTypes);
|
||||
if (sourceChild != targetChild)
|
||||
deepCopyRelationships(opcPackage, sourceChild, targetChild, relationshipTypes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static Part deepCopyPart(OpcPackage opcPackage, Base targetParent, Part sourcePart, Set<String> relationshipTypes) throws Docx4JException {
|
||||
Part ret = opcPackage.getParts().get(sourcePart.getPartName());
|
||||
if (ret == null) {
|
||||
ret = copyPart(sourcePart, opcPackage, (relationshipTypes == null || relationshipTypes.contains(sourcePart.getRelationshipType())));
|
||||
opcPackage.getParts().put(ret);
|
||||
targetParent.setPartShortcut(ret, ret.getRelationshipType());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected static Part copyPart(Part part, OpcPackage targetPackage, boolean deepCopy) throws Docx4JException {
|
||||
Part ret = null;
|
||||
try {
|
||||
ret = part.getClass().getConstructor(PartName.class).newInstance(part.getPartName());
|
||||
} catch (Exception e) {
|
||||
throw new Docx4JException("Error cloning part of class " + part.getClass().getName(), e);
|
||||
}
|
||||
ret.setRelationshipType(part.getRelationshipType());
|
||||
ret.setContentType(new ContentType(part.getContentType()));
|
||||
if (targetPackage != null)
|
||||
ret.setPackage(targetPackage);
|
||||
if (deepCopy) {
|
||||
deepCopyContent(part, ret);
|
||||
} else {
|
||||
shallowCopyContent(part, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected static void deepCopyContent(Part source, Part destination) throws Docx4JException {
|
||||
if (source instanceof BinaryPart) {
|
||||
byte[] byteData = new byte[((BinaryPart)source).getBuffer().limit()];
|
||||
((BinaryPart)source).getBuffer().get(byteData);
|
||||
((BinaryPart)destination).setBinaryData(ByteBuffer.wrap(byteData));
|
||||
} else if (source instanceof JaxbXmlPart) {
|
||||
((JaxbXmlPart)destination).setJaxbElement(XmlUtils.deepCopy(((JaxbXmlPart)source).getJaxbElement(), ((JaxbXmlPart)source).getJAXBContext()));
|
||||
((JaxbXmlPart)destination).setJAXBContext(((JaxbXmlPart)source).getJAXBContext());
|
||||
if (log.isDebugEnabled() && source instanceof org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart) {
|
||||
log.debug("source: " + ((JaxbXmlPart)source).getXML());
|
||||
log.debug("destination: " + ((JaxbXmlPart)destination).getXML());
|
||||
}
|
||||
} else if (source instanceof CustomXmlDataStoragePart) {
|
||||
CustomXmlDataStorage dataStorage = ((CustomXmlDataStoragePart)source).getData().factory();
|
||||
dataStorage.setDocument((Document)((CustomXmlDataStoragePart)source).getData().getDocument().cloneNode(true));
|
||||
((CustomXmlDataStoragePart)destination).setData(dataStorage);
|
||||
} else if (source instanceof XmlPart) {
|
||||
((XmlPart)destination).setDocument((Document)((XmlPart)source).getDocument().cloneNode(true));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Dont know how to handle a part of type " + source.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
protected static void shallowCopyContent(Part source, Part destination) throws Docx4JException {
|
||||
if (source instanceof BinaryPart) {
|
||||
((BinaryPart)destination).setBinaryData(((BinaryPart)source).getBuffer());
|
||||
} else if (source instanceof JaxbXmlPart) {
|
||||
((JaxbXmlPart)destination).setJaxbElement(((JaxbXmlPart)source).getJaxbElement());
|
||||
((JaxbXmlPart)destination).setJAXBContext(((JaxbXmlPart)source).getJAXBContext());
|
||||
} else if (source instanceof CustomXmlDataStoragePart) {
|
||||
((CustomXmlDataStoragePart)destination).setData(((CustomXmlDataStoragePart)source).getData());
|
||||
} else if (source instanceof XmlPart) {
|
||||
((XmlPart)destination).setDocument(((XmlPart)source).getDocument());
|
||||
} else {
|
||||
throw new IllegalArgumentException("Dont know how to handle a part of type " + source.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
package org.docx4j.convert.out.common.wrappers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import org.docx4j.TraversalUtil;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.convert.out.common.ConversionSectionWrapper;
|
||||
import org.docx4j.convert.out.common.ConversionSectionWrappers;
|
||||
import org.docx4j.convert.out.common.preprocess.PageNumberInformation;
|
||||
import org.docx4j.convert.out.common.preprocess.PageNumberInformationCollector;
|
||||
import org.docx4j.jaxb.Context;
|
||||
import org.docx4j.model.structure.HeaderFooterPolicy;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
|
||||
import org.docx4j.wml.BooleanDefaultTrue;
|
||||
import org.docx4j.wml.Document;
|
||||
import org.docx4j.wml.P;
|
||||
import org.docx4j.wml.PPr;
|
||||
import org.docx4j.wml.STPageOrientation;
|
||||
import org.docx4j.wml.SdtBlock;
|
||||
import org.docx4j.wml.SectPr;
|
||||
import org.jvnet.jaxb2_commons.ppp.Child;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ConversionSectionWrapperFactory {
|
||||
protected static Logger log = LoggerFactory.getLogger(ConversionSectionWrapperFactory.class);
|
||||
|
||||
protected static class SdtBlockFinder extends TraversalUtil.CallbackImpl {
|
||||
List<SdtBlock> sdtBlocks = new ArrayList<SdtBlock>();
|
||||
|
||||
LinkedList<SdtBlock> ll = new LinkedList<SdtBlock>();
|
||||
|
||||
public List<Object> apply(Object o) {
|
||||
if (o instanceof P && ((P)o).getPPr() != null && ((P)o).getPPr().getSectPr() != null)
|
||||
for (SdtBlock sdt : this.ll) {
|
||||
if (!this.sdtBlocks.contains(sdt))
|
||||
this.sdtBlocks.add(sdt);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void walkJAXBElements(Object parent) {
|
||||
List<Object> children = getChildren(parent);
|
||||
if (children != null)
|
||||
for (Object o : children) {
|
||||
o = XmlUtils.unwrap(o);
|
||||
if (o instanceof Child)
|
||||
if (parent instanceof SdtBlock) {
|
||||
((Child)o).setParent(((SdtBlock)parent).getSdtContent().getContent());
|
||||
} else {
|
||||
((Child)o).setParent(parent);
|
||||
}
|
||||
apply(o);
|
||||
if (o instanceof SdtBlock)
|
||||
this.ll.addLast((SdtBlock)o);
|
||||
if (shouldTraverse(o))
|
||||
walkJAXBElements(o);
|
||||
if (o instanceof SdtBlock)
|
||||
this.ll.removeLast();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static ConversionSectionWrappers process(WordprocessingMLPackage wmlPackage, boolean dummySections, boolean dummyPageNumbering) throws Docx4JException {
|
||||
List<ConversionSectionWrapper> conversionSections = null;
|
||||
Document document = wmlPackage.getMainDocumentPart().getContents();
|
||||
RelationshipsPart rels = wmlPackage.getMainDocumentPart().getRelationshipsPart();
|
||||
BooleanDefaultTrue evenAndOddHeaders = null;
|
||||
if (wmlPackage.getMainDocumentPart().getDocumentSettingsPart() != null && wmlPackage.getMainDocumentPart().getDocumentSettingsPart().getContents() != null)
|
||||
evenAndOddHeaders = wmlPackage.getMainDocumentPart().getDocumentSettingsPart().getContents().getEvenAndOddHeaders();
|
||||
if (dummySections) {
|
||||
conversionSections = processDummy(wmlPackage, document, rels, evenAndOddHeaders, dummyPageNumbering);
|
||||
} else {
|
||||
conversionSections = processComplete(wmlPackage, document, rels, evenAndOddHeaders, dummyPageNumbering);
|
||||
}
|
||||
return new ConversionSectionWrappers(conversionSections);
|
||||
}
|
||||
|
||||
protected static List<ConversionSectionWrapper> processDummy(WordprocessingMLPackage wmlPackage, Document document, RelationshipsPart rels, BooleanDefaultTrue evenAndOddHeaders, boolean dummyPageNumbering) {
|
||||
log.debug("starting");
|
||||
List<ConversionSectionWrapper> conversionSections = new ArrayList<ConversionSectionWrapper>();
|
||||
ConversionSectionWrapper currentSectionWrapper = null;
|
||||
HeaderFooterPolicy previousHF = new HeaderFooterPolicy(document.getBody().getSectPr(), null, rels, evenAndOddHeaders);
|
||||
currentSectionWrapper = createSectionWrapper(document.getBody().getSectPr(), previousHF, rels, evenAndOddHeaders, 1, document.getBody().getContent(), dummyPageNumbering);
|
||||
conversionSections.add(currentSectionWrapper);
|
||||
return conversionSections;
|
||||
}
|
||||
|
||||
protected static ConversionSectionWrapper createSectionWrapper(SectPr sectPr, HeaderFooterPolicy headerFooterPolicy, RelationshipsPart rels, BooleanDefaultTrue evenAndOddHeaders, int conversionSectionIndex, List<Object> content, boolean dummyPageNumbering) {
|
||||
ConversionSectionWrapper csw = new ConversionSectionWrapper(sectPr, headerFooterPolicy, rels, evenAndOddHeaders, "s" + Integer.toString(conversionSectionIndex), content);
|
||||
PageNumberInformation pageNumberInformation = PageNumberInformationCollector.process(csw, dummyPageNumbering);
|
||||
csw.setPageNumberInformation(pageNumberInformation);
|
||||
return csw;
|
||||
}
|
||||
|
||||
protected static List<ConversionSectionWrapper> processComplete(WordprocessingMLPackage wmlPackage, Document document, RelationshipsPart rels, BooleanDefaultTrue evenAndOddHeaders, boolean dummyPageNumbering) {
|
||||
log.debug("starting");
|
||||
removeContentControls(document);
|
||||
List<SectPr> sectPrs = getSectPrs(document);
|
||||
List<ConversionSectionWrapper> conversionSections = new ArrayList<ConversionSectionWrapper>();
|
||||
ConversionSectionWrapper currentSectionWrapper = null;
|
||||
HeaderFooterPolicy previousHF = null;
|
||||
int conversionSectionIndex = 0;
|
||||
List<Object> sectionContent = new ArrayList();
|
||||
int sectPrIndex = 0;
|
||||
for (Object o : document.getBody().getContent()) {
|
||||
if (o instanceof P)
|
||||
if (((P)o).getPPr() != null) {
|
||||
PPr ppr = ((P)o).getPPr();
|
||||
if (ppr.getSectPr() != null) {
|
||||
boolean ignoreThisSection = false;
|
||||
SectPr followingSectPr = sectPrs.get(++sectPrIndex);
|
||||
if (followingSectPr.getType() != null && followingSectPr.getType().getVal().equals("continuous")) {
|
||||
log.info("following sectPr is continuous; this section wrapper must include its contents ");
|
||||
ignoreThisSection = true;
|
||||
}
|
||||
if (ignoreThisSection) {
|
||||
previousHF = new HeaderFooterPolicy(ppr.getSectPr(), previousHF, rels, evenAndOddHeaders);
|
||||
SectPr.PgSz pgSzThis = ppr.getSectPr().getPgSz();
|
||||
SectPr.PgSz pgSzNext = followingSectPr.getPgSz();
|
||||
if (insertPageBreak(pgSzThis, pgSzNext))
|
||||
ppr.setPageBreakBefore(new BooleanDefaultTrue());
|
||||
} else {
|
||||
currentSectionWrapper = createSectionWrapper(ppr.getSectPr(), previousHF, rels, evenAndOddHeaders, ++conversionSectionIndex, sectionContent, dummyPageNumbering);
|
||||
conversionSections.add(currentSectionWrapper);
|
||||
previousHF = currentSectionWrapper.getHeaderFooterPolicy();
|
||||
sectionContent = new ArrayList();
|
||||
}
|
||||
}
|
||||
}
|
||||
sectionContent.add(o);
|
||||
}
|
||||
currentSectionWrapper = createSectionWrapper(document.getBody().getSectPr(), previousHF, rels, evenAndOddHeaders, ++conversionSectionIndex, sectionContent, dummyPageNumbering);
|
||||
conversionSections.add(currentSectionWrapper);
|
||||
return conversionSections;
|
||||
}
|
||||
|
||||
private static boolean insertPageBreak(SectPr.PgSz pgSzThis, SectPr.PgSz pgSzNext) {
|
||||
boolean insertPageBreak = false;
|
||||
if (pgSzThis != null && pgSzNext != null) {
|
||||
if (pgSzThis.getH().compareTo(pgSzNext.getH()) != 0)
|
||||
insertPageBreak = true;
|
||||
if (pgSzThis.getW().compareTo(pgSzNext.getW()) != 0)
|
||||
insertPageBreak = true;
|
||||
boolean portraitThis = true;
|
||||
if (pgSzThis.getOrient() != null)
|
||||
portraitThis = pgSzThis.getOrient().equals(STPageOrientation.PORTRAIT);
|
||||
boolean portraitNext = true;
|
||||
if (pgSzNext.getOrient() != null)
|
||||
portraitNext = pgSzNext.getOrient().equals(STPageOrientation.PORTRAIT);
|
||||
if (portraitThis != portraitNext)
|
||||
insertPageBreak = true;
|
||||
}
|
||||
return insertPageBreak;
|
||||
}
|
||||
|
||||
private static void removeContentControls(Document document) {
|
||||
SdtBlockFinder sbr = new SdtBlockFinder();
|
||||
new TraversalUtil(document.getContent(), sbr);
|
||||
for (int i = sbr.sdtBlocks.size() - 1; i >= 0; i--) {
|
||||
SdtBlock sdtBlock = sbr.sdtBlocks.get(i);
|
||||
List<Object> parentList = null;
|
||||
if (sdtBlock.getParent() instanceof ArrayList) {
|
||||
parentList = (ArrayList)sdtBlock.getParent();
|
||||
} else {
|
||||
log.error("Handle " + sdtBlock.getParent().getClass().getName());
|
||||
}
|
||||
int index = parentList.indexOf(sdtBlock);
|
||||
parentList.remove(index);
|
||||
parentList.addAll(index, sdtBlock.getSdtContent().getContent());
|
||||
}
|
||||
}
|
||||
|
||||
private static List<SectPr> getSectPrs(Document document) {
|
||||
List<SectPr> sectPrs = new ArrayList<SectPr>();
|
||||
for (Object o : document.getBody().getContent()) {
|
||||
if (o instanceof P && (
|
||||
(P)o).getPPr() != null) {
|
||||
PPr ppr = ((P)o).getPPr();
|
||||
if (ppr.getSectPr() != null)
|
||||
sectPrs.add(ppr.getSectPr());
|
||||
}
|
||||
}
|
||||
if (document.getBody().getSectPr() != null) {
|
||||
sectPrs.add(document.getBody().getSectPr());
|
||||
} else {
|
||||
log.debug("No body level sectPr in document");
|
||||
List<Object> all = document.getBody().getContent();
|
||||
Object last = all.get(all.size() - 1);
|
||||
if (last instanceof P && ((P)last).getPPr() != null && ((P)last).getPPr().getSectPr() != null) {
|
||||
log.debug(".. but last p contains sectPr .. move it");
|
||||
SectPr thisSectPr = ((P)last).getPPr().getSectPr();
|
||||
document.getBody().setSectPr(thisSectPr);
|
||||
((P)last).getPPr().setSectPr(null);
|
||||
sectPrs.remove(thisSectPr);
|
||||
} else {
|
||||
document.getBody().setSectPr(Context.getWmlObjectFactory().createSectPr());
|
||||
sectPrs.add(document.getBody().getSectPr());
|
||||
}
|
||||
}
|
||||
return sectPrs;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package org.docx4j.convert.out.common.writer;
|
||||
|
||||
public abstract class AbstractBookmarkStartWriter extends AbstractSimpleWriter {
|
||||
public static final String WRITER_ID = "w:bookmarkStart";
|
||||
|
||||
protected AbstractBookmarkStartWriter() {
|
||||
super("w:bookmarkStart");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package org.docx4j.convert.out.common.writer;
|
||||
|
||||
public abstract class AbstractBrWriter extends AbstractSimpleWriter {
|
||||
public static final String WRITER_ID = "w:br";
|
||||
|
||||
protected AbstractBrWriter() {
|
||||
super("w:br");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,224 @@
|
|||
package org.docx4j.convert.out.common.writer;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.docx4j.convert.out.common.AbstractWmlConversionContext;
|
||||
import org.docx4j.convert.out.common.Writer;
|
||||
import org.docx4j.model.fields.FieldValueException;
|
||||
import org.docx4j.model.fields.FldSimpleModel;
|
||||
import org.docx4j.model.fields.FormattingSwitchHelper;
|
||||
import org.docx4j.model.fields.docproperty.DocPropertyResolver;
|
||||
import org.docx4j.model.properties.Property;
|
||||
import org.docx4j.model.properties.PropertyFactory;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.wml.CTSimpleField;
|
||||
import org.docx4j.wml.R;
|
||||
import org.docx4j.wml.RPr;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
public abstract class AbstractFldSimpleWriter extends AbstractSimpleWriter {
|
||||
public static final String WRITER_ID = "w:fldSimple";
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(AbstractFldSimpleWriter.class);
|
||||
|
||||
protected static class DateHandler implements FldSimpleStringWriterHandler {
|
||||
public String getName() {
|
||||
return "DATE";
|
||||
}
|
||||
|
||||
public String toString(AbstractWmlConversionContext context, FldSimpleModel model) throws TransformerException {
|
||||
return FormattingSwitchHelper.formatDate(model);
|
||||
}
|
||||
}
|
||||
|
||||
protected static class TimeHandler implements FldSimpleStringWriterHandler {
|
||||
public String getName() {
|
||||
return "TIME";
|
||||
}
|
||||
|
||||
public String toString(AbstractWmlConversionContext context, FldSimpleModel model) throws TransformerException {
|
||||
return FormattingSwitchHelper.formatDate(model);
|
||||
}
|
||||
}
|
||||
|
||||
protected static class PrintdateHandler implements FldSimpleStringWriterHandler {
|
||||
public String getName() {
|
||||
return "PRINTDATE";
|
||||
}
|
||||
|
||||
public String toString(AbstractWmlConversionContext context, FldSimpleModel model) throws TransformerException {
|
||||
return FormattingSwitchHelper.formatDate(model);
|
||||
}
|
||||
}
|
||||
|
||||
protected static class DocPropertyHandler implements FldSimpleStringWriterHandler {
|
||||
public String getName() {
|
||||
return "DOCPROPERTY";
|
||||
}
|
||||
|
||||
public String toString(AbstractWmlConversionContext context, FldSimpleModel model) throws TransformerException {
|
||||
DocPropertyResolver dpr = new DocPropertyResolver(context.getWmlPackage());
|
||||
List<String> params = model.getFldParameters();
|
||||
String key = model.getFldParameterString();
|
||||
try {
|
||||
String value = dpr.getValue(key).toString();
|
||||
AbstractFldSimpleWriter.log.debug("= " + value);
|
||||
return FormattingSwitchHelper.applyFormattingSwitch(context.getWmlPackage(), model, value);
|
||||
} catch (FieldValueException e) {
|
||||
if (e.getMessage().contains("No value found for DOCPROPERTY PAGES"));
|
||||
throw new TransformerException(e);
|
||||
} catch (Docx4JException e) {
|
||||
throw new TransformerException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Map<String, FldSimpleWriterHandler> handlers = new HashMap<String, FldSimpleWriterHandler>();
|
||||
|
||||
protected FldSimpleNodeWriterHandler defaultHandler = null;
|
||||
|
||||
protected String elementNs = null;
|
||||
|
||||
protected String elementName = null;
|
||||
|
||||
protected AbstractFldSimpleWriter(String elementNs, String elementName) {
|
||||
super("w:fldSimple");
|
||||
registerHandlers();
|
||||
this.defaultHandler = createDefaultHandler();
|
||||
this.elementNs = elementNs;
|
||||
this.elementName = elementName;
|
||||
}
|
||||
|
||||
protected void registerHandlers() {
|
||||
registerHandler(new DateHandler());
|
||||
registerHandler(new TimeHandler());
|
||||
registerHandler(new PrintdateHandler());
|
||||
registerHandler(new DocPropertyHandler());
|
||||
}
|
||||
|
||||
protected void registerHandler(FldSimpleWriterHandler handler) {
|
||||
this.handlers.put(handler.getName(), handler);
|
||||
}
|
||||
|
||||
protected FldSimpleNodeWriterHandler createDefaultHandler() {
|
||||
return new FldSimpleNodeWriterHandler() {
|
||||
public String getName() {
|
||||
return "*";
|
||||
}
|
||||
|
||||
public Node toNode(AbstractWmlConversionContext context, FldSimpleModel model, Document doc) throws TransformerException {
|
||||
return model.getContent();
|
||||
}
|
||||
|
||||
public int getProcessType() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Node toNode(AbstractWmlConversionContext context, Object unmarshalledNode, Node content, Writer.TransformState state, Document doc) throws TransformerException {
|
||||
FldSimpleModel fldSimpleModel = new FldSimpleModel();
|
||||
fldSimpleModel.build((CTSimpleField)unmarshalledNode, content);
|
||||
log.debug("looking for handler for " + fldSimpleModel.getFldName());
|
||||
FldSimpleWriterHandler handler = this.handlers.get(fldSimpleModel.getFldName());
|
||||
FldSimpleNodeWriterHandler nodeHandler = null;
|
||||
Node ret = null;
|
||||
String value = null;
|
||||
if (handler == null) {
|
||||
handler = this.defaultHandler;
|
||||
log.debug(".. using defaultHandler");
|
||||
} else {
|
||||
log.debug(".. got it .. " + handler.getClass().getName());
|
||||
}
|
||||
if (handler instanceof FldSimpleNodeWriterHandler) {
|
||||
nodeHandler = (FldSimpleNodeWriterHandler)handler;
|
||||
ret = nodeHandler.toNode(context, fldSimpleModel, doc);
|
||||
switch (nodeHandler.getProcessType()) {
|
||||
case 1:
|
||||
applyStyle(context, fldSimpleModel, ret);
|
||||
break;
|
||||
case 2:
|
||||
ret = wrap(context, ret, doc);
|
||||
applyStyle(context, fldSimpleModel, ret);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
value = ((FldSimpleStringWriterHandler)handler).toString(context, fldSimpleModel);
|
||||
ret = wrap(context, value, doc);
|
||||
applyStyle(context, fldSimpleModel, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected Node wrap(AbstractWmlConversionContext context, String result, Document doc) {
|
||||
RPr rPr = null;
|
||||
Node node = null;
|
||||
if (result != null) {
|
||||
node = createNode(doc);
|
||||
if (result.length() > 0)
|
||||
node.setTextContent(result);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
protected Node wrap(AbstractWmlConversionContext context, Node node, Document doc) {
|
||||
Node wrapper = null;
|
||||
if (node != null) {
|
||||
wrapper = createNode(doc);
|
||||
wrapper.appendChild(node);
|
||||
}
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
protected void applyStyle(AbstractWmlConversionContext context, FldSimpleModel fldSimpleModel, Node node) {
|
||||
CTSimpleField ctSimpleField = fldSimpleModel.getFldSimple();
|
||||
RPr rPr = null;
|
||||
if (node != null) {
|
||||
rPr = getRPr(ctSimpleField.getContent());
|
||||
if (rPr != null) {
|
||||
List<Property> properties = PropertyFactory.createProperties(context.getWmlPackage(), rPr);
|
||||
if (properties != null && !properties.isEmpty())
|
||||
applyProperties(properties, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Node createNode(Document doc) {
|
||||
return (this.elementNs != null && this.elementNs.length() > 0) ? doc.createElementNS(this.elementNs, this.elementName) : doc.createElement(this.elementName);
|
||||
}
|
||||
|
||||
private RPr getRPr(List<Object> content) {
|
||||
for (int i = 0; i < content.size(); i++) {
|
||||
if (content.get(i) instanceof R)
|
||||
return ((R)content.get(i)).getRPr();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected abstract void applyProperties(List<Property> paramList, Node paramNode);
|
||||
|
||||
public static interface FldSimpleStringWriterHandler extends FldSimpleWriterHandler {
|
||||
String toString(AbstractWmlConversionContext param1AbstractWmlConversionContext, FldSimpleModel param1FldSimpleModel) throws TransformerException;
|
||||
}
|
||||
|
||||
public static interface FldSimpleNodeWriterHandler extends FldSimpleWriterHandler {
|
||||
public static final int PROCESS_NONE = 0;
|
||||
|
||||
public static final int PROCESS_APPLY_STYLE = 1;
|
||||
|
||||
public static final int PROCESS_WRAP_APPLY_STYLE = 2;
|
||||
|
||||
int getProcessType();
|
||||
|
||||
Node toNode(AbstractWmlConversionContext param1AbstractWmlConversionContext, FldSimpleModel param1FldSimpleModel, Document param1Document) throws TransformerException;
|
||||
}
|
||||
|
||||
public static interface FldSimpleWriterHandler {
|
||||
String getName();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package org.docx4j.convert.out.common.writer;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.docx4j.convert.out.common.AbstractWmlConversionContext;
|
||||
import org.docx4j.convert.out.common.Writer;
|
||||
import org.docx4j.model.fields.FldSimpleModel;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
public abstract class AbstractHyperlinkWriter extends AbstractSimpleWriter implements AbstractFldSimpleWriter.FldSimpleNodeWriterHandler {
|
||||
public static final String WRITER_ID = "w:hyperlink";
|
||||
|
||||
protected static final String HYPERLINK_NAME = "HYPERLINK";
|
||||
|
||||
protected AbstractHyperlinkWriter() {
|
||||
super("w:hyperlink");
|
||||
}
|
||||
|
||||
public Node toNode(AbstractWmlConversionContext context, Object unmarshalledNode, Node content, Writer.TransformState state, Document doc) throws TransformerException {
|
||||
AbstractHyperlinkWriterModel hyperlinkModel = new AbstractHyperlinkWriterModel();
|
||||
Node ret = null;
|
||||
hyperlinkModel.build(context, unmarshalledNode, content);
|
||||
ret = toNode(context, hyperlinkModel, doc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected abstract Node toNode(AbstractWmlConversionContext paramAbstractWmlConversionContext, AbstractHyperlinkWriterModel paramAbstractHyperlinkWriterModel, Document paramDocument) throws TransformerException;
|
||||
|
||||
public String getName() {
|
||||
return "HYPERLINK";
|
||||
}
|
||||
|
||||
public int getProcessType() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Node toNode(AbstractWmlConversionContext context, FldSimpleModel model, Document doc) throws TransformerException {
|
||||
AbstractHyperlinkWriterModel hyperlinkModel = new AbstractHyperlinkWriterModel();
|
||||
hyperlinkModel.build(context, model, model.getContent());
|
||||
return toNode(context, hyperlinkModel, doc);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
package org.docx4j.convert.out.common.writer;
|
||||
|
||||
import java.util.List;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.docx4j.convert.out.ConversionHyperlinkHandler;
|
||||
import org.docx4j.convert.out.common.AbstractWmlConversionContext;
|
||||
import org.docx4j.model.fields.FldSimpleModel;
|
||||
import org.docx4j.model.fields.FormattingSwitchHelper;
|
||||
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
|
||||
import org.docx4j.relationships.Relationship;
|
||||
import org.docx4j.wml.P;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
public class AbstractHyperlinkWriterModel implements ConversionHyperlinkHandler.Model {
|
||||
private static Logger log = LoggerFactory.getLogger(AbstractHyperlinkWriterModel.class);
|
||||
|
||||
protected Node content = null;
|
||||
|
||||
protected String target = null;
|
||||
|
||||
protected boolean external = false;
|
||||
|
||||
protected String anchor = null;
|
||||
|
||||
protected String docLocation = null;
|
||||
|
||||
protected String rId = null;
|
||||
|
||||
protected String tgtFrame = null;
|
||||
|
||||
protected String tooltip = null;
|
||||
|
||||
public void build(AbstractWmlConversionContext conversionContext, Object node, Node content) throws TransformerException {
|
||||
Relationship relationship = null;
|
||||
RelationshipsPart rPart = null;
|
||||
P.Hyperlink pHyperlink = (P.Hyperlink)node;
|
||||
this.content = content;
|
||||
setAnchor(pHyperlink.getAnchor());
|
||||
setDocLocation(pHyperlink.getDocLocation());
|
||||
setRId(pHyperlink.getId());
|
||||
setTgtFrame(pHyperlink.getTgtFrame());
|
||||
setTooltip(pHyperlink.getTooltip());
|
||||
if (conversionContext.getCurrentPart() == null) {
|
||||
log.warn("set currentPart (via conversionContext)");
|
||||
} else if (getRId() != null && getRId().length() > 0) {
|
||||
rPart = conversionContext.getCurrentPart().getRelationshipsPart();
|
||||
if (rPart == null) {
|
||||
log.error("RelationshipsPart is missing!");
|
||||
} else {
|
||||
log.debug("looking for rel" + getRId());
|
||||
relationship = rPart.getRelationshipByID(getRId());
|
||||
if (relationship != null && "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink".equals(relationship.getType())) {
|
||||
setTarget(relationship.getTarget());
|
||||
setExternal("External".equals(relationship.getTargetMode()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void build(AbstractWmlConversionContext conversionContext, FldSimpleModel fldSimpleModel, Node content) throws TransformerException {
|
||||
int idx = 0;
|
||||
List<String> parameters = fldSimpleModel.getFldParameters();
|
||||
String parameter = null;
|
||||
boolean isSwitch = false;
|
||||
char switchChar = '\000';
|
||||
String switchParameter = null;
|
||||
this.content = content;
|
||||
while (idx < parameters.size()) {
|
||||
parameter = parameters.get(idx);
|
||||
if (parameter != null && parameter.length() > 0) {
|
||||
isSwitch = (parameter.charAt(0) == '\\' && parameter.length() == 2);
|
||||
if (isSwitch) {
|
||||
switchChar = Character.toLowerCase(parameter.charAt(1));
|
||||
switch (switchChar) {
|
||||
case 'l':
|
||||
switchParameter = FormattingSwitchHelper.getSwitchValue(idx + 1, parameters);
|
||||
if (switchParameter != null) {
|
||||
setTarget(switchParameter);
|
||||
idx++;
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
switchParameter = FormattingSwitchHelper.getSwitchValue(idx + 1, parameters);
|
||||
if (switchParameter != null) {
|
||||
setTgtFrame(switchParameter);
|
||||
idx++;
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
setTgtFrame("_blank");
|
||||
break;
|
||||
case 'o':
|
||||
switchParameter = FormattingSwitchHelper.getSwitchValue(idx + 1, parameters);
|
||||
if (switchParameter != null) {
|
||||
setTooltip(switchParameter);
|
||||
idx++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (idx == 0) {
|
||||
setTarget(FormattingSwitchHelper.getSwitchValue(idx, parameters));
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
if (getTarget() != null && getTarget().length() > 0 && (getTarget().indexOf('/') > -1 || getTarget().indexOf('\\') > -1 || getTarget().indexOf('.') > -1 || getTarget().indexOf(':') > -1))
|
||||
setExternal(true);
|
||||
}
|
||||
|
||||
public String getExternalTarget() {
|
||||
return isExternal() ? getTarget() : null;
|
||||
}
|
||||
|
||||
public String getInternalTarget() {
|
||||
String ret = isExternal() ? null : getTarget();
|
||||
if (ret == null)
|
||||
ret = getAnchor();
|
||||
if (ret == null)
|
||||
ret = getDocLocation();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public String getTarget() {
|
||||
return this.target;
|
||||
}
|
||||
|
||||
public void setTarget(String target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public boolean isExternal() {
|
||||
return this.external;
|
||||
}
|
||||
|
||||
public void setExternal(boolean external) {
|
||||
this.external = external;
|
||||
}
|
||||
|
||||
public String getAnchor() {
|
||||
return this.anchor;
|
||||
}
|
||||
|
||||
public void setAnchor(String anchor) {
|
||||
this.anchor = anchor;
|
||||
}
|
||||
|
||||
public String getDocLocation() {
|
||||
return this.docLocation;
|
||||
}
|
||||
|
||||
public void setDocLocation(String docLocation) {
|
||||
this.docLocation = docLocation;
|
||||
}
|
||||
|
||||
public String getRId() {
|
||||
return this.rId;
|
||||
}
|
||||
|
||||
public void setRId(String rId) {
|
||||
this.rId = rId;
|
||||
}
|
||||
|
||||
public String getTgtFrame() {
|
||||
return this.tgtFrame;
|
||||
}
|
||||
|
||||
public void setTgtFrame(String tgtFrame) {
|
||||
this.tgtFrame = tgtFrame;
|
||||
}
|
||||
|
||||
public String getTooltip() {
|
||||
return this.tooltip;
|
||||
}
|
||||
|
||||
public void setTooltip(String tooltip) {
|
||||
this.tooltip = tooltip;
|
||||
}
|
||||
|
||||
public Node getContent() {
|
||||
return this.content;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "HyperlinkModel [target=" + this.target + ", external=" + this.external + ", anchor=" + this.anchor + ", docLocation=" + this.docLocation + ", rId=" + this.rId + ", tgtFrame=" + this.tgtFrame + "]";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
package org.docx4j.convert.out.common.writer;
|
||||
|
||||
import java.io.StringReader;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.convert.out.common.AbstractConversionContext;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.traversal.NodeIterator;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
public abstract class AbstractMessageWriter {
|
||||
public DocumentFragment notImplemented(AbstractConversionContext context, NodeIterator nodes, String message) {
|
||||
Node n = nodes.nextNode();
|
||||
context.getLog().warn("NOT IMPLEMENTED: support for " + n.getNodeName() + "; " + message);
|
||||
if (context.getLog().isDebugEnabled()) {
|
||||
if (message == null)
|
||||
message = "";
|
||||
context.getLog().debug(XmlUtils.w3CDomNodeToString(n));
|
||||
return message(context, "NOT IMPLEMENTED: support for " + n.getNodeName() + " - " + message);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public DocumentFragment message(AbstractConversionContext context, String message) {
|
||||
if (!context.getLog().isDebugEnabled())
|
||||
return null;
|
||||
String documentFragment = getOutputPrefix() + message + getOutputSuffix();
|
||||
context.getLog().debug(documentFragment);
|
||||
StringReader reader = new StringReader(documentFragment);
|
||||
InputSource inputSource = new InputSource(reader);
|
||||
Document doc = null;
|
||||
try {
|
||||
doc = XmlUtils.getNewDocumentBuilder().parse(inputSource);
|
||||
} catch (Exception e) {
|
||||
context.getLog().error(e.getMessage(), (Throwable)e);
|
||||
}
|
||||
reader.close();
|
||||
DocumentFragment docfrag = doc.createDocumentFragment();
|
||||
docfrag.appendChild(doc.getDocumentElement());
|
||||
return docfrag;
|
||||
}
|
||||
|
||||
protected abstract String getOutputPrefix();
|
||||
|
||||
protected abstract String getOutputSuffix();
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
package org.docx4j.convert.out.common.writer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.convert.out.common.AbstractWmlConversionContext;
|
||||
import org.docx4j.model.fields.FldSimpleModel;
|
||||
import org.docx4j.model.fields.FormattingSwitchHelper;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
public abstract class AbstractPagerefHandler implements AbstractFldSimpleWriter.FldSimpleNodeWriterHandler {
|
||||
protected int outputType = -1;
|
||||
|
||||
protected AbstractPagerefHandler(int outputType) {
|
||||
this.outputType = outputType;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "PAGEREF";
|
||||
}
|
||||
|
||||
public int getProcessType() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Node toNode(AbstractWmlConversionContext context, FldSimpleModel model, Document doc) throws TransformerException {
|
||||
String bookmarkId = model.getFldParameters().get(0);
|
||||
Node content = model.getContent();
|
||||
Node literalNode = null;
|
||||
AbstractHyperlinkWriterModel hyperlinkModel = null;
|
||||
DocumentFragment docFrag = null;
|
||||
String textcontent = null;
|
||||
List<String> textcontentitems = null;
|
||||
String textcontentitem = null;
|
||||
if (FormattingSwitchHelper.hasSwitch("\\p", model.getFldParameters())) {
|
||||
textcontent = getTextcontent(content);
|
||||
textcontentitems = splitTextcontent(textcontent);
|
||||
if (textcontentitems != null) {
|
||||
docFrag = doc.createDocumentFragment();
|
||||
for (int i = 0; i < textcontentitems.size(); i++) {
|
||||
textcontentitem = textcontentitems.get(i);
|
||||
if ("#".equals(textcontentitem)) {
|
||||
docFrag.appendChild(createPageref(context, doc, bookmarkId));
|
||||
} else {
|
||||
literalNode = doc.createDocumentFragment();
|
||||
XmlUtils.treeCopy(content, literalNode);
|
||||
literalNode = literalNode.getFirstChild();
|
||||
setTextcontent(literalNode, textcontentitem);
|
||||
docFrag.appendChild(literalNode);
|
||||
}
|
||||
}
|
||||
content = docFrag;
|
||||
}
|
||||
} else {
|
||||
content = doc.createDocumentFragment();
|
||||
content.appendChild(createPageref(context, doc, bookmarkId));
|
||||
}
|
||||
if (FormattingSwitchHelper.hasSwitch("\\h", model.getFldParameters())) {
|
||||
hyperlinkModel = new AbstractHyperlinkWriterModel();
|
||||
hyperlinkModel.build(context, model, content);
|
||||
content = HyperlinkUtil.toNode(this.outputType, context, hyperlinkModel, content, doc);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
protected List<String> splitTextcontent(String textcontent) {
|
||||
List<String> ret = null;
|
||||
int startPos = 0;
|
||||
int endPos = -1;
|
||||
if (textcontent != null && textcontent.length() > 0) {
|
||||
while (startPos < textcontent.length() && !Character.isDigit(textcontent.charAt(startPos)))
|
||||
startPos++;
|
||||
endPos = startPos + 1;
|
||||
while (endPos < textcontent.length() && Character.isDigit(textcontent.charAt(endPos)))
|
||||
endPos++;
|
||||
if (startPos < endPos && endPos <= textcontent.length()) {
|
||||
ret = new ArrayList<String>();
|
||||
if (startPos > 0)
|
||||
ret.add(textcontent.substring(0, startPos));
|
||||
ret.add("#");
|
||||
if (endPos < textcontent.length())
|
||||
ret.add(textcontent.substring(endPos));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected String getTextcontent(Node root) {
|
||||
Node textNode = findTextNode(root);
|
||||
return (textNode != null) ? textNode.getNodeValue() : null;
|
||||
}
|
||||
|
||||
protected void setTextcontent(Node root, String text) {
|
||||
Node textNode = findTextNode(root);
|
||||
if (textNode != null) {
|
||||
if (text.charAt(text.length() - 1) == ' ')
|
||||
text = text.substring(0, text.length() - 1) + '\u00A0';
|
||||
if (text.charAt(0) == ' ')
|
||||
if (text.length() > 1) {
|
||||
text = '\u00A0' + text.substring(1);
|
||||
} else {
|
||||
text = Character.toString('\u00A0');
|
||||
}
|
||||
textNode.setNodeValue(text);
|
||||
}
|
||||
}
|
||||
|
||||
protected Node findTextNode(Node root) {
|
||||
int i;
|
||||
Node ret = null;
|
||||
NodeList childNodes = null;
|
||||
Node childNode = null;
|
||||
switch (root.getNodeType()) {
|
||||
case 3:
|
||||
ret = (root.getNodeValue() != null && root.getNodeValue().length() > 0) ? root : null;
|
||||
break;
|
||||
case 1:
|
||||
case 9:
|
||||
case 11:
|
||||
childNodes = root.getChildNodes();
|
||||
for (i = 0; ret == null && i < childNodes.getLength(); i++)
|
||||
ret = findTextNode(childNodes.item(i));
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected abstract Node createPageref(AbstractWmlConversionContext paramAbstractWmlConversionContext, Document paramDocument, String paramString);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package org.docx4j.convert.out.common.writer;
|
||||
|
||||
public abstract class AbstractPictWriter extends AbstractSimpleWriter {
|
||||
public static final String WRITER_ID = "w:pict";
|
||||
|
||||
protected AbstractPictWriter() {
|
||||
super("w:pict");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package org.docx4j.convert.out.common.writer;
|
||||
|
||||
import org.docx4j.convert.out.common.Writer;
|
||||
|
||||
public abstract class AbstractSimpleWriter implements Writer {
|
||||
protected String writerId = null;
|
||||
|
||||
protected AbstractSimpleWriter(String writerId) {
|
||||
this.writerId = writerId;
|
||||
}
|
||||
|
||||
public String getID() {
|
||||
return this.writerId;
|
||||
}
|
||||
|
||||
public Writer.TransformState createTransformState() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package org.docx4j.convert.out.common.writer;
|
||||
|
||||
public abstract class AbstractSymbolWriter extends AbstractSimpleWriter {
|
||||
public static final String WRITER_ID = "w:sym";
|
||||
|
||||
protected AbstractSymbolWriter() {
|
||||
super("w:sym");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,411 @@
|
|||
package org.docx4j.convert.out.common.writer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.docx4j.UnitsOfMeasurement;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.convert.out.common.AbstractWmlConversionContext;
|
||||
import org.docx4j.convert.out.common.Writer;
|
||||
import org.docx4j.jaxb.Context;
|
||||
import org.docx4j.model.properties.Property;
|
||||
import org.docx4j.model.properties.PropertyFactory;
|
||||
import org.docx4j.model.properties.table.BorderBottom;
|
||||
import org.docx4j.model.properties.table.BorderLeft;
|
||||
import org.docx4j.model.properties.table.BorderRight;
|
||||
import org.docx4j.model.properties.table.BorderTop;
|
||||
import org.docx4j.model.properties.table.CellMarginBottom;
|
||||
import org.docx4j.model.properties.table.CellMarginLeft;
|
||||
import org.docx4j.model.properties.table.CellMarginRight;
|
||||
import org.docx4j.model.properties.table.CellMarginTop;
|
||||
import org.docx4j.model.properties.table.tc.Shading;
|
||||
import org.docx4j.model.properties.table.tc.TextAlignmentVertical;
|
||||
import org.docx4j.model.properties.table.tr.TrCantSplit;
|
||||
import org.docx4j.model.properties.table.tr.TrHeight;
|
||||
import org.docx4j.wml.BooleanDefaultTrue;
|
||||
import org.docx4j.wml.CTBorder;
|
||||
import org.docx4j.wml.CTHeight;
|
||||
import org.docx4j.wml.CTShd;
|
||||
import org.docx4j.wml.CTTblCellMar;
|
||||
import org.docx4j.wml.CTTblPrBase;
|
||||
import org.docx4j.wml.CTTblPrEx;
|
||||
import org.docx4j.wml.STBorder;
|
||||
import org.docx4j.wml.STShd;
|
||||
import org.docx4j.wml.TblBorders;
|
||||
import org.docx4j.wml.TblGridCol;
|
||||
import org.docx4j.wml.TcPr;
|
||||
import org.docx4j.wml.TrPr;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.DOMException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
public abstract class AbstractTableWriter extends AbstractSimpleWriter {
|
||||
private static Logger log = LoggerFactory.getLogger(AbstractTableWriter.class);
|
||||
|
||||
public static final String WRITER_ID = "w:tbl";
|
||||
|
||||
protected static final int NODE_TABLE = 0;
|
||||
|
||||
protected static final int NODE_TABLE_COLUMN_GROUP = 1;
|
||||
|
||||
protected static final int NODE_TABLE_COLUMN = 2;
|
||||
|
||||
protected static final int NODE_TABLE_HEADER = 3;
|
||||
|
||||
protected static final int NODE_TABLE_HEADER_ROW = 4;
|
||||
|
||||
protected static final int NODE_TABLE_HEADER_CELL = 5;
|
||||
|
||||
protected static final int NODE_TABLE_BODY = 6;
|
||||
|
||||
protected static final int NODE_TABLE_BODY_ROW = 7;
|
||||
|
||||
protected static final int NODE_TABLE_BODY_CELL = 8;
|
||||
|
||||
protected static final Map<String, Integer> PATTERN_PERCENTAGES = new TreeMap<String, Integer>();
|
||||
|
||||
static {
|
||||
PATTERN_PERCENTAGES.put("diagCross", Integer.valueOf(50));
|
||||
PATTERN_PERCENTAGES.put("horzCross", Integer.valueOf(50));
|
||||
PATTERN_PERCENTAGES.put("thinDiagCross", Integer.valueOf(25));
|
||||
PATTERN_PERCENTAGES.put("thinHorzCross", Integer.valueOf(25));
|
||||
PATTERN_PERCENTAGES.put("pct5", Integer.valueOf(5));
|
||||
PATTERN_PERCENTAGES.put("pct10", Integer.valueOf(10));
|
||||
PATTERN_PERCENTAGES.put("pct12", Integer.valueOf(12));
|
||||
PATTERN_PERCENTAGES.put("pct15", Integer.valueOf(15));
|
||||
PATTERN_PERCENTAGES.put("pct20", Integer.valueOf(20));
|
||||
PATTERN_PERCENTAGES.put("pct25", Integer.valueOf(25));
|
||||
PATTERN_PERCENTAGES.put("pct30", Integer.valueOf(30));
|
||||
PATTERN_PERCENTAGES.put("pct35", Integer.valueOf(35));
|
||||
PATTERN_PERCENTAGES.put("pct37", Integer.valueOf(37));
|
||||
PATTERN_PERCENTAGES.put("pct40", Integer.valueOf(40));
|
||||
PATTERN_PERCENTAGES.put("pct45", Integer.valueOf(45));
|
||||
PATTERN_PERCENTAGES.put("pct50", Integer.valueOf(50));
|
||||
PATTERN_PERCENTAGES.put("pct55", Integer.valueOf(55));
|
||||
PATTERN_PERCENTAGES.put("pct60", Integer.valueOf(60));
|
||||
PATTERN_PERCENTAGES.put("pct62", Integer.valueOf(62));
|
||||
PATTERN_PERCENTAGES.put("pct65", Integer.valueOf(65));
|
||||
PATTERN_PERCENTAGES.put("pct70", Integer.valueOf(70));
|
||||
PATTERN_PERCENTAGES.put("pct75", Integer.valueOf(75));
|
||||
PATTERN_PERCENTAGES.put("pct80", Integer.valueOf(80));
|
||||
PATTERN_PERCENTAGES.put("pct85", Integer.valueOf(85));
|
||||
PATTERN_PERCENTAGES.put("pct87", Integer.valueOf(87));
|
||||
PATTERN_PERCENTAGES.put("pct90", Integer.valueOf(90));
|
||||
PATTERN_PERCENTAGES.put("pct95", Integer.valueOf(95));
|
||||
PATTERN_PERCENTAGES.put("solid", Integer.valueOf(100));
|
||||
}
|
||||
|
||||
protected static class TableModelTransformState implements Writer.TransformState {
|
||||
int idx = 0;
|
||||
|
||||
public int getIdx() {
|
||||
return this.idx;
|
||||
}
|
||||
|
||||
public void incrementIdx() {
|
||||
this.idx++;
|
||||
}
|
||||
}
|
||||
|
||||
protected AbstractTableWriter() {
|
||||
super("w:tbl");
|
||||
}
|
||||
|
||||
public Writer.TransformState createTransformState() {
|
||||
return new TableModelTransformState();
|
||||
}
|
||||
|
||||
public Node toNode(AbstractWmlConversionContext context, Object unmarshalledNode, Node content, Writer.TransformState transformState, Document doc) throws TransformerException {
|
||||
Node ret = null;
|
||||
AbstractTableWriterModel table = new AbstractTableWriterModel();
|
||||
table.build(context, unmarshalledNode, content);
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("Table asXML:\n" + table.debugStr());
|
||||
if (!table.getCells().isEmpty())
|
||||
ret = toNode(context, table, transformState, doc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected Node toNode(AbstractWmlConversionContext context, AbstractTableWriterModel table, Writer.TransformState transformState, Document doc) throws TransformerException {
|
||||
DocumentFragment docfrag = doc.createDocumentFragment();
|
||||
Element tableRoot = createNode(doc, null, 0);
|
||||
List<Property> rowProperties = new ArrayList<Property>();
|
||||
int rowPropertiesTableSize = -1;
|
||||
List<Property> cellProperties = new ArrayList<Property>();
|
||||
int cellPropertiesTableSize = -1;
|
||||
int cellPropertiesRowSize = -1;
|
||||
boolean inHeader = (table.getHeaderMaxRow() > -1);
|
||||
AbstractTableWriterModelRow rowModel = null;
|
||||
Element rowContainer = null;
|
||||
Element row = null;
|
||||
Element cellNode = null;
|
||||
createRowProperties(rowProperties, table.getEffectiveTableStyle().getTrPr(), true);
|
||||
rowPropertiesTableSize = rowProperties.size();
|
||||
createCellProperties(cellProperties, table.getEffectiveTableStyle().getTrPr());
|
||||
createCellProperties(cellProperties, table.getEffectiveTableStyle().getTcPr());
|
||||
createCellProperties(cellProperties, table.getEffectiveTableStyle().getTblPr());
|
||||
cellPropertiesTableSize = cellProperties.size();
|
||||
docfrag.appendChild(tableRoot);
|
||||
applyTableStyles(context, table, transformState, tableRoot);
|
||||
createColumns(context, table, transformState, doc, tableRoot);
|
||||
rowContainer = createNode(doc, tableRoot, inHeader ? 3 : 6);
|
||||
tableRoot.appendChild(rowContainer);
|
||||
applyTableRowContainerCustomAttributes(context, table, transformState, rowContainer, inHeader);
|
||||
for (int rowIndex = 0; rowIndex < table.getCells().size(); rowIndex++) {
|
||||
rowModel = table.getCells().get(rowIndex);
|
||||
if (inHeader && rowIndex > table.getHeaderMaxRow()) {
|
||||
rowContainer = createNode(doc, tableRoot, 6);
|
||||
tableRoot.appendChild(rowContainer);
|
||||
inHeader = false;
|
||||
applyTableRowContainerCustomAttributes(context, table, transformState, rowContainer, inHeader);
|
||||
}
|
||||
row = createNode(doc, rowContainer, inHeader ? 4 : 7);
|
||||
TrPr trPr = rowModel.getRowProperties();
|
||||
CTTblPrEx tblPrEx = rowModel.getRowPropertiesExceptions();
|
||||
createRowProperties(rowProperties, trPr, false);
|
||||
processAttributes(context, rowProperties, row);
|
||||
applyTableRowCustomAttributes(context, table, transformState, row, rowIndex, inHeader);
|
||||
createCellProperties(cellProperties, trPr);
|
||||
createCellProperties(cellProperties, tblPrEx);
|
||||
cellPropertiesRowSize = cellProperties.size();
|
||||
for (AbstractTableWriterModelCell cell : rowModel.getRowContents()) {
|
||||
if (cell.isDummy()) {
|
||||
if (!cell.isVMerged()) {
|
||||
cellNode = createNode(doc, row, inHeader ? 5 : 8);
|
||||
row.appendChild(cellNode);
|
||||
applyTableCellCustomAttributes(context, table, transformState, cell, cellNode, inHeader, true);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
cellNode = createNode(doc, row, inHeader ? 5 : 8);
|
||||
row.appendChild(cellNode);
|
||||
createCellProperties(cellProperties, cell.getTcPr());
|
||||
processAttributes(context, cellProperties, cellNode);
|
||||
applyTableCellCustomAttributes(context, table, transformState, cell, cellNode, inHeader, false);
|
||||
resetProperties(cellProperties, cellPropertiesRowSize);
|
||||
if (cell.getContent() == null) {
|
||||
log.warn("model cell had no contents!");
|
||||
continue;
|
||||
}
|
||||
log.debug("copying cell contents..");
|
||||
XmlUtils.treeCopy(cell.getContent().getChildNodes(), cellNode);
|
||||
}
|
||||
resetProperties(cellProperties, cellPropertiesTableSize);
|
||||
resetProperties(rowProperties, rowPropertiesTableSize);
|
||||
}
|
||||
return docfrag;
|
||||
}
|
||||
|
||||
protected Element createNode(Document doc, Element parent, int nodeType) {
|
||||
Element ret = createNode(doc, nodeType);
|
||||
if (ret != null && parent != null)
|
||||
parent.appendChild(ret);
|
||||
return (ret != null) ? ret : parent;
|
||||
}
|
||||
|
||||
protected void createColumns(AbstractWmlConversionContext context, AbstractTableWriterModel table, Writer.TransformState transformState, Document doc, Element tableRoot) throws DOMException {
|
||||
List<TblGridCol> gridCols = (table.getTblGrid() != null) ? table.getTblGrid().getGridCol() : null;
|
||||
Element columnGroup = createNode(doc, tableRoot, 1);
|
||||
Element column = null;
|
||||
applyColumnGroupCustomAttributes(context, table, transformState, columnGroup);
|
||||
if (gridCols != null && !gridCols.isEmpty()) {
|
||||
for (int i = 0; i < gridCols.size(); i++) {
|
||||
column = createNode(doc, columnGroup, 2);
|
||||
applyColumnCustomAttributes(context, table, transformState, column, i, gridCols.get(i).getW().intValue());
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < table.getColCount(); i++) {
|
||||
column = createNode(doc, columnGroup, 2);
|
||||
applyColumnCustomAttributes(context, table, transformState, column, i, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void applyTableStyles(AbstractWmlConversionContext context, AbstractTableWriterModel table, Writer.TransformState transformState, Element tableRoot) {
|
||||
List<Property> tableProperties = null;
|
||||
if (table.getEffectiveTableStyle().getTblPr() == null) {
|
||||
log.warn("table.getEffectiveTableStyle().getTblPr() is null, but should never be");
|
||||
return;
|
||||
}
|
||||
tableProperties = PropertyFactory.createProperties(table.getEffectiveTableStyle().getTblPr());
|
||||
if (table.getEffectiveTableStyle().getTcPr() != null)
|
||||
PropertyFactory.createPropertiesTable(tableProperties, table.getEffectiveTableStyle().getTcPr());
|
||||
if (table.getEffectiveTableStyle().getTcPr() == null || table.getEffectiveTableStyle().getTcPr().getVAlign() == null)
|
||||
tableProperties.add(new TextAlignmentVertical());
|
||||
if (!table.isDrawTableBorders()) {
|
||||
for (int i = tableProperties.size() - 1; i >= 0; i--) {
|
||||
if (tableProperties.get(i) instanceof Shading || tableProperties.get(i) instanceof org.docx4j.model.properties.table.AbstractBorder)
|
||||
tableProperties.remove(i);
|
||||
}
|
||||
appendNoneBordersAndShading(tableProperties);
|
||||
}
|
||||
processAttributes(context, tableProperties, tableRoot);
|
||||
applyTableCustomAttributes(context, table, transformState, tableRoot);
|
||||
}
|
||||
|
||||
protected void appendNoneBordersAndShading(List<Property> tableProperties) {
|
||||
CTBorder ctBrdr = null;
|
||||
CTShd shd = Context.getWmlObjectFactory().createCTShd();
|
||||
ctBrdr = Context.getWmlObjectFactory().createCTBorder();
|
||||
ctBrdr.setVal(STBorder.NONE);
|
||||
tableProperties.add(new BorderLeft(ctBrdr));
|
||||
ctBrdr = Context.getWmlObjectFactory().createCTBorder();
|
||||
ctBrdr.setVal(STBorder.NONE);
|
||||
tableProperties.add(new BorderRight(ctBrdr));
|
||||
ctBrdr = Context.getWmlObjectFactory().createCTBorder();
|
||||
ctBrdr.setVal(STBorder.NONE);
|
||||
tableProperties.add(new BorderTop(ctBrdr));
|
||||
ctBrdr = Context.getWmlObjectFactory().createCTBorder();
|
||||
ctBrdr.setVal(STBorder.NONE);
|
||||
tableProperties.add(new BorderBottom(ctBrdr));
|
||||
shd.setColor("auto");
|
||||
shd.setFill("auto");
|
||||
shd.setVal(STShd.CLEAR);
|
||||
tableProperties.add(new Shading(shd));
|
||||
}
|
||||
|
||||
protected void createRowProperties(List<Property> properties, TrPr trPr, boolean includeDefaultHeight) {
|
||||
JAXBElement<CTHeight> trHeight = (trPr != null) ? (JAXBElement)getElement(trPr.getCnfStyleOrDivIdOrGridBefore(), "trHeight") : null;
|
||||
if (trHeight != null)
|
||||
properties.add(new TrHeight((CTHeight)trHeight.getValue()));
|
||||
if (trPr != null) {
|
||||
JAXBElement<?> cantSplit = XmlUtils.getListItemByQName(trPr.getCnfStyleOrDivIdOrGridBefore(), new QName("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "cantSplit"));
|
||||
if (cantSplit != null) {
|
||||
BooleanDefaultTrue val = (BooleanDefaultTrue)XmlUtils.unwrap(cantSplit);
|
||||
if (val.isVal())
|
||||
properties.add(new TrCantSplit(cantSplit));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void createCellProperties(List<Property> properties, TrPr trPr) {}
|
||||
|
||||
protected void createCellProperties(List<Property> properties, CTTblPrBase tblPr) {
|
||||
if (tblPr == null) {
|
||||
log.warn("table.getEffectiveTableStyle().getTblPr() is null, but should never be");
|
||||
return;
|
||||
}
|
||||
TblBorders tblBorders = tblPr.getTblBorders();
|
||||
CTTblCellMar tblCellMargin = tblPr.getTblCellMar();
|
||||
if (tblBorders != null) {
|
||||
if (tblBorders.getInsideH() != null) {
|
||||
properties.add(new BorderTop(tblBorders.getTop()));
|
||||
properties.add(new BorderBottom(tblBorders.getBottom()));
|
||||
}
|
||||
if (tblBorders.getInsideV() != null) {
|
||||
properties.add(new BorderRight(tblBorders.getRight()));
|
||||
properties.add(new BorderLeft(tblBorders.getLeft()));
|
||||
}
|
||||
}
|
||||
if (tblCellMargin != null) {
|
||||
if (tblCellMargin.getTop() != null)
|
||||
properties.add(new CellMarginTop(tblCellMargin.getTop()));
|
||||
if (tblCellMargin.getBottom() != null)
|
||||
properties.add(new CellMarginBottom(tblCellMargin.getBottom()));
|
||||
if (tblCellMargin.getLeft() != null)
|
||||
properties.add(new CellMarginLeft(tblCellMargin.getLeft()));
|
||||
if (tblCellMargin.getRight() != null)
|
||||
properties.add(new CellMarginRight(tblCellMargin.getRight()));
|
||||
}
|
||||
}
|
||||
|
||||
protected void createCellProperties(List<Property> properties, TcPr tcPr) {
|
||||
if (tcPr != null)
|
||||
PropertyFactory.createProperties(properties, tcPr);
|
||||
}
|
||||
|
||||
protected void createCellProperties(List<Property> properties, CTTblPrEx tblPrEx) {}
|
||||
|
||||
protected JAXBElement<?> getElement(List<JAXBElement<?>> cnfStyleOrDivIdOrGridBefore, String localName) {
|
||||
JAXBElement<?> element = null;
|
||||
if (cnfStyleOrDivIdOrGridBefore != null && !cnfStyleOrDivIdOrGridBefore.isEmpty())
|
||||
for (int i = 0; i < cnfStyleOrDivIdOrGridBefore.size(); i++) {
|
||||
element = cnfStyleOrDivIdOrGridBefore.get(i);
|
||||
if (localName.equals(element.getName().getLocalPart()))
|
||||
return element;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void processAttributes(AbstractWmlConversionContext context, List<Property> properties, Element element) {
|
||||
CTShd shd = null;
|
||||
int bgColor = 16777215;
|
||||
int fgColor = 0;
|
||||
int pctPattern = -1;
|
||||
for (int i = 0; i < properties.size(); i++) {
|
||||
if (properties.get(i) instanceof Shading) {
|
||||
shd = (CTShd)properties.get(i).getObject();
|
||||
fgColor = extractColor(shd.getColor(), 0);
|
||||
if (shd.getVal() != null && "clear".equals(shd.getVal().value()) && "auto".equals(shd.getFill())) {
|
||||
bgColor = 16777215;
|
||||
pctPattern = -2;
|
||||
} else {
|
||||
pctPattern = (shd.getVal() != null) ? extractPattern(shd.getVal().value()) : -1;
|
||||
bgColor = extractColor(shd.getFill(), bgColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pctPattern == -1) {
|
||||
applyAttributes(context, properties, element);
|
||||
} else {
|
||||
properties.add(createShading(fgColor, bgColor, pctPattern));
|
||||
applyAttributes(context, properties, element);
|
||||
properties.remove(properties.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
protected int extractPattern(String pattern) {
|
||||
return (pattern != null && PATTERN_PERCENTAGES.containsKey(pattern)) ? PATTERN_PERCENTAGES.get(pattern) : -1;
|
||||
}
|
||||
|
||||
protected int extractColor(String value, int defaultColor) {
|
||||
int ret = defaultColor;
|
||||
if (value != null && !"auto".equals(value))
|
||||
try {
|
||||
ret = Integer.parseInt(value, 16);
|
||||
} catch (NumberFormatException nfe) {}
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected Property createShading(int fgColor, int bgColor, int pctFg) {
|
||||
CTShd shd = null;
|
||||
int resColor = UnitsOfMeasurement.combineColors(fgColor, bgColor, pctFg);
|
||||
shd = Context.getWmlObjectFactory().createCTShd();
|
||||
shd.setVal(STShd.CLEAR);
|
||||
shd.setFill(calcHexColor(resColor));
|
||||
return new Shading(shd);
|
||||
}
|
||||
|
||||
protected String calcHexColor(int value) {
|
||||
String ret = Integer.toHexString(value).toUpperCase();
|
||||
return (ret.length() < 6) ? ("000000".substring(0, 6 - ret.length()) + ret) : ret;
|
||||
}
|
||||
|
||||
protected void resetProperties(List<Property> properties, int size) {
|
||||
for (; properties.size() > size; properties.remove(properties.size() - 1));
|
||||
}
|
||||
|
||||
protected void applyTableCustomAttributes(AbstractWmlConversionContext context, AbstractTableWriterModel table, Writer.TransformState transformState, Element tableRoot) {}
|
||||
|
||||
protected void applyColumnGroupCustomAttributes(AbstractWmlConversionContext context, AbstractTableWriterModel table, Writer.TransformState transformState, Element columnGroup) {}
|
||||
|
||||
protected void applyColumnCustomAttributes(AbstractWmlConversionContext context, AbstractTableWriterModel table, Writer.TransformState transformState, Element column, int columnIndex, int columnWidth) {}
|
||||
|
||||
protected void applyTableRowContainerCustomAttributes(AbstractWmlConversionContext context, AbstractTableWriterModel table, Writer.TransformState transformState, Element rowContainer, boolean isHeader) {}
|
||||
|
||||
protected void applyTableRowCustomAttributes(AbstractWmlConversionContext context, AbstractTableWriterModel table, Writer.TransformState transformState, Element row, int rowIndex, boolean isHeader) {}
|
||||
|
||||
protected void applyTableCellCustomAttributes(AbstractWmlConversionContext context, AbstractTableWriterModel table, Writer.TransformState transformState, AbstractTableWriterModelCell tableCell, Element cellNode, boolean isHeader, boolean isDummyCell) {}
|
||||
|
||||
protected abstract Element createNode(Document paramDocument, int paramInt);
|
||||
|
||||
protected abstract void applyAttributes(AbstractWmlConversionContext paramAbstractWmlConversionContext, List<Property> paramList, Element paramElement);
|
||||
}
|
||||
|
|
@ -0,0 +1,345 @@
|
|||
package org.docx4j.convert.out.common.writer;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.docx4j.TraversalUtil;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.convert.out.common.AbstractWmlConversionContext;
|
||||
import org.docx4j.finders.TcFinder;
|
||||
import org.docx4j.jaxb.Context;
|
||||
import org.docx4j.model.PropertyResolver;
|
||||
import org.docx4j.wml.BooleanDefaultTrue;
|
||||
import org.docx4j.wml.CTTblPrBase;
|
||||
import org.docx4j.wml.CTTrPrBase;
|
||||
import org.docx4j.wml.Style;
|
||||
import org.docx4j.wml.Tbl;
|
||||
import org.docx4j.wml.TblGrid;
|
||||
import org.docx4j.wml.TblGridCol;
|
||||
import org.docx4j.wml.TblPr;
|
||||
import org.docx4j.wml.Tc;
|
||||
import org.docx4j.wml.Tr;
|
||||
import org.docx4j.wml.TrPr;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
public class AbstractTableWriterModel {
|
||||
private static final Logger log = LoggerFactory.getLogger(AbstractTableWriterModel.class);
|
||||
|
||||
private static final int DEFAULT_PAGE_WIDTH_TWIPS = 12240;
|
||||
|
||||
protected List<AbstractTableWriterModelRow> cells;
|
||||
|
||||
private int headerMaxRow;
|
||||
|
||||
private int row;
|
||||
|
||||
private int col;
|
||||
|
||||
public AbstractTableWriterModel() {
|
||||
resetIndexes();
|
||||
this.cells = new ArrayList<AbstractTableWriterModelRow>();
|
||||
this.headerMaxRow = -1;
|
||||
}
|
||||
|
||||
private int width = -1;
|
||||
|
||||
private boolean drawTableBorder = true;
|
||||
|
||||
protected String styleId;
|
||||
|
||||
protected Style effectiveTableStyle;
|
||||
|
||||
protected TblPr tblPr;
|
||||
|
||||
protected TblGrid tblGrid;
|
||||
|
||||
public String getStyleId() {
|
||||
return this.styleId;
|
||||
}
|
||||
|
||||
public Style getEffectiveTableStyle() {
|
||||
return this.effectiveTableStyle;
|
||||
}
|
||||
|
||||
public TblPr getTblPr() {
|
||||
return this.tblPr;
|
||||
}
|
||||
|
||||
public TblGrid getTblGrid() {
|
||||
return this.tblGrid;
|
||||
}
|
||||
|
||||
boolean borderConflictResolutionRequired = true;
|
||||
|
||||
public boolean isBorderConflictResolutionRequired() {
|
||||
return this.borderConflictResolutionRequired;
|
||||
}
|
||||
|
||||
public boolean isDrawTableBorders() {
|
||||
return this.drawTableBorder;
|
||||
}
|
||||
|
||||
public int getTableWidth() {
|
||||
return this.width;
|
||||
}
|
||||
|
||||
public void resetIndexes() {
|
||||
this.row = -1;
|
||||
this.col = -1;
|
||||
}
|
||||
|
||||
public void startRow(Tr tr) {
|
||||
this.cells.add(new AbstractTableWriterModelRow(tr));
|
||||
this.row++;
|
||||
this.col = -1;
|
||||
}
|
||||
|
||||
public void addCell(Tc tc, Node content) {
|
||||
addCell(new AbstractTableWriterModelCell(this, this.row, ++this.col, tc, content));
|
||||
}
|
||||
|
||||
private void addDummyCell() {
|
||||
addDummyCell(0);
|
||||
}
|
||||
|
||||
private void addDummyCell(int colSpan) {
|
||||
AbstractTableWriterModelCell cell = new AbstractTableWriterModelCell(this, this.row, ++this.col);
|
||||
if (colSpan > 0)
|
||||
cell.colspan = colSpan;
|
||||
addCell(cell);
|
||||
}
|
||||
|
||||
private void addCell(AbstractTableWriterModelCell cell) {
|
||||
this.cells.get(this.row).add(cell);
|
||||
}
|
||||
|
||||
public AbstractTableWriterModelCell getCell(int row, int col) {
|
||||
return this.cells.get(row).get(col);
|
||||
}
|
||||
|
||||
public String getColName(int col) {
|
||||
return "col" + String.valueOf(col + 1);
|
||||
}
|
||||
|
||||
public int getColCount() {
|
||||
return this.cells.get(0).size();
|
||||
}
|
||||
|
||||
public List<AbstractTableWriterModelRow> getCells() {
|
||||
return this.cells;
|
||||
}
|
||||
|
||||
public int getHeaderMaxRow() {
|
||||
return this.headerMaxRow;
|
||||
}
|
||||
|
||||
public void build(AbstractWmlConversionContext conversionContext, Object node, Node content) throws TransformerException {
|
||||
Tbl tbl = null;
|
||||
try {
|
||||
tbl = (Tbl)node;
|
||||
} catch (ClassCastException e) {
|
||||
throw new TransformerException("Node is not of the type Tbl it is " + node.getClass().getName());
|
||||
}
|
||||
if (tbl.getTblPr() != null && tbl.getTblPr().getTblStyle() != null)
|
||||
this.styleId = tbl.getTblPr().getTblStyle().getVal();
|
||||
this.tblGrid = tbl.getTblGrid();
|
||||
this.tblPr = tbl.getTblPr();
|
||||
PropertyResolver pr = conversionContext.getPropertyResolver();
|
||||
this.effectiveTableStyle = pr.getEffectiveTableStyle(tbl.getTblPr());
|
||||
NodeList cellContents = content.getChildNodes();
|
||||
TrFinder trFinder = new TrFinder();
|
||||
new TraversalUtil(tbl, trFinder);
|
||||
ensureFoTableBody(trFinder.trList);
|
||||
int r = 0;
|
||||
for (Tr tr : trFinder.trList) {
|
||||
startRow(tr);
|
||||
handleRow(cellContents, tr, r);
|
||||
r++;
|
||||
if (this.cells.get(this.row).getRowContents().isEmpty()) {
|
||||
this.cells.remove(this.row);
|
||||
this.row--;
|
||||
r--;
|
||||
}
|
||||
}
|
||||
CTTblPrBase tblPr = this.effectiveTableStyle.getTblPr();
|
||||
if (tblPr != null &&
|
||||
tblPr.getTblCellSpacing() != null)
|
||||
this.borderConflictResolutionRequired = false;
|
||||
this.width = calcTableWidth();
|
||||
}
|
||||
|
||||
private void ensureFoTableBody(List<Tr> rows) {
|
||||
int numRows = rows.size();
|
||||
if (numRows == 0) {
|
||||
log.warn("Encountered table with no rows");
|
||||
return;
|
||||
}
|
||||
Tr lastRow = rows.get(numRows - 1);
|
||||
if (isHeaderRow(lastRow)) {
|
||||
List<JAXBElement<?>> cnfStyleOrDivIdOrGridBefore = lastRow.getTrPr().getCnfStyleOrDivIdOrGridBefore();
|
||||
JAXBElement<?> tblHeader = getElement(cnfStyleOrDivIdOrGridBefore, "tblHeader");
|
||||
cnfStyleOrDivIdOrGridBefore.remove(tblHeader);
|
||||
}
|
||||
int indexOfLastHeaderRow = -1;
|
||||
for (int j = rows.size(); j > 0; j--) {
|
||||
Tr tr = rows.get(j - 1);
|
||||
if (isHeaderRow(tr)) {
|
||||
indexOfLastHeaderRow = j - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < indexOfLastHeaderRow; i++) {
|
||||
Tr tr = rows.get(i);
|
||||
if (!isHeaderRow(tr)) {
|
||||
TrPr trpr = null;
|
||||
if (tr.getTrPr() == null) {
|
||||
trpr = Context.getWmlObjectFactory().createTrPr();
|
||||
tr.setTrPr(trpr);
|
||||
}
|
||||
BooleanDefaultTrue booleandefaulttrue = Context.getWmlObjectFactory().createBooleanDefaultTrue();
|
||||
JAXBElement<BooleanDefaultTrue> booleandefaulttrueWrapped = Context.getWmlObjectFactory().createCTTrPrBaseTblHeader(booleandefaulttrue);
|
||||
trpr.getCnfStyleOrDivIdOrGridBefore().add(booleandefaulttrueWrapped);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class TrFinder extends TraversalUtil.CallbackImpl {
|
||||
List<Tr> trList = new ArrayList<Tr>();
|
||||
|
||||
public List<Object> apply(Object o) {
|
||||
if (o instanceof Tr)
|
||||
this.trList.add((Tr)o);
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean shouldTraverse(Object o) {
|
||||
return !(o instanceof Tbl);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleRow(NodeList cellContents, Tr tr, int r) {
|
||||
int gridAfter = getGridAfter(tr);
|
||||
int gridBefore = getGridBefore(tr);
|
||||
boolean headerRow = isHeaderRow(tr);
|
||||
log.debug("Processing r " + r);
|
||||
if (this.borderConflictResolutionRequired && tr.getTblPrEx() != null && tr.getTblPrEx().getTblCellSpacing() != null)
|
||||
this.borderConflictResolutionRequired = false;
|
||||
if (headerRow && this.headerMaxRow < r)
|
||||
this.headerMaxRow = r;
|
||||
if (this.drawTableBorder)
|
||||
this.drawTableBorder = (gridBefore == 0 && gridAfter == 0);
|
||||
TcFinder tcFinder = new TcFinder();
|
||||
new TraversalUtil(tr, tcFinder);
|
||||
if (gridBefore > 0)
|
||||
addDummyCell(gridBefore);
|
||||
int c = 0;
|
||||
log.debug("Processing c " + c);
|
||||
for (Tc tc : tcFinder.tcList) {
|
||||
Node wtrNode = cellContents.item(r);
|
||||
if (wtrNode == null)
|
||||
log.warn("Couldn't find item " + r);
|
||||
addCell(tc, getTc(wtrNode, c, new IntRef(0)));
|
||||
c++;
|
||||
}
|
||||
if (gridAfter > 0)
|
||||
addDummyCell(gridAfter);
|
||||
}
|
||||
|
||||
protected boolean isHeaderRow(Tr tr) {
|
||||
List<JAXBElement<?>> cnfStyleOrDivIdOrGridBefore = (tr.getTrPr() != null) ? tr.getTrPr().getCnfStyleOrDivIdOrGridBefore() : null;
|
||||
JAXBElement<?> element = getElement(cnfStyleOrDivIdOrGridBefore, "tblHeader");
|
||||
BooleanDefaultTrue boolVal = (element != null) ? (BooleanDefaultTrue)element.getValue() : null;
|
||||
return (boolVal != null) ? boolVal.isVal() : false;
|
||||
}
|
||||
|
||||
protected int getGridAfter(Tr tr) {
|
||||
List<JAXBElement<?>> cnfStyleOrDivIdOrGridBefore = (tr.getTrPr() != null) ? tr.getTrPr().getCnfStyleOrDivIdOrGridBefore() : null;
|
||||
JAXBElement<?> element = getElement(cnfStyleOrDivIdOrGridBefore, "gridAfter");
|
||||
CTTrPrBase.GridAfter gridAfter = (element != null) ? (CTTrPrBase.GridAfter)element.getValue() : null;
|
||||
BigInteger val = (gridAfter != null) ? gridAfter.getVal() : null;
|
||||
return (val != null) ? val.intValue() : 0;
|
||||
}
|
||||
|
||||
protected int getGridBefore(Tr tr) {
|
||||
List<JAXBElement<?>> cnfStyleOrDivIdOrGridBefore = (tr.getTrPr() != null) ? tr.getTrPr().getCnfStyleOrDivIdOrGridBefore() : null;
|
||||
JAXBElement<?> element = getElement(cnfStyleOrDivIdOrGridBefore, "gridBefore");
|
||||
CTTrPrBase.GridBefore gridBefore = (element != null) ? (CTTrPrBase.GridBefore)element.getValue() : null;
|
||||
BigInteger val = (gridBefore != null) ? gridBefore.getVal() : null;
|
||||
return (val != null) ? val.intValue() : 0;
|
||||
}
|
||||
|
||||
protected JAXBElement<?> getElement(List<JAXBElement<?>> cnfStyleOrDivIdOrGridBefore, String localName) {
|
||||
JAXBElement<?> element = null;
|
||||
if (cnfStyleOrDivIdOrGridBefore != null && !cnfStyleOrDivIdOrGridBefore.isEmpty())
|
||||
for (int i = 0; i < cnfStyleOrDivIdOrGridBefore.size(); i++) {
|
||||
element = cnfStyleOrDivIdOrGridBefore.get(i);
|
||||
if (localName.equals(element.getName().getLocalPart()))
|
||||
return element;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected int calcTableWidth() {
|
||||
int ret = -1;
|
||||
List<TblGridCol> gridCols = (getTblGrid() != null) ? getTblGrid().getGridCol() : null;
|
||||
if (gridCols != null && !gridCols.isEmpty()) {
|
||||
ret = 0;
|
||||
for (int i = 0; i < gridCols.size(); i++)
|
||||
ret += gridCols.get(i).getW().intValue();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private Node getTc(Node wtrNode, int wanted, IntRef current) {
|
||||
for (int i = 0; i < wtrNode.getChildNodes().getLength(); i++) {
|
||||
Node thisChild = wtrNode.getChildNodes().item(i);
|
||||
if (thisChild.getNodeType() == 1) {
|
||||
log.debug("Looking at " + thisChild.getLocalName() + "; have encountered " + current.i);
|
||||
if (thisChild.getLocalName().equals("tc")) {
|
||||
if (current.i == wanted)
|
||||
return thisChild;
|
||||
current.increment();
|
||||
} else {
|
||||
Node n = getTc(thisChild, wanted, current);
|
||||
if (n != null)
|
||||
return n;
|
||||
}
|
||||
}
|
||||
}
|
||||
log.error("Couldn't find tc in: " + XmlUtils.w3CDomNodeToString(wtrNode));
|
||||
return null;
|
||||
}
|
||||
|
||||
static class IntRef {
|
||||
int i;
|
||||
|
||||
IntRef(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
void increment() {
|
||||
this.i++;
|
||||
}
|
||||
}
|
||||
|
||||
public String debugStr() {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (AbstractTableWriterModelRow row : this.cells) {
|
||||
List<AbstractTableWriterModelCell> rowContents = row.getRowContents();
|
||||
for (AbstractTableWriterModelCell c : rowContents) {
|
||||
if (c == null) {
|
||||
buf.append("null ");
|
||||
continue;
|
||||
}
|
||||
buf.append(c.debugStr());
|
||||
}
|
||||
buf.append("\n");
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
package org.docx4j.convert.out.common.writer;
|
||||
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.wml.Tc;
|
||||
import org.docx4j.wml.TcPr;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
public class AbstractTableWriterModelCell {
|
||||
private static final Logger logger = LoggerFactory.getLogger(AbstractTableWriterModelCell.class);
|
||||
|
||||
private AbstractTableWriterModel table;
|
||||
|
||||
private int row;
|
||||
|
||||
private int col;
|
||||
|
||||
protected int rowspan = 0;
|
||||
|
||||
protected int colspan = 0;
|
||||
|
||||
protected boolean dummy = false;
|
||||
|
||||
protected Node content = null;
|
||||
|
||||
TcPr tcPr;
|
||||
|
||||
public TcPr getTcPr() {
|
||||
return this.tcPr;
|
||||
}
|
||||
|
||||
public AbstractTableWriterModelCell(AbstractTableWriterModel table, int row, int col) {
|
||||
this.table = table;
|
||||
this.row = row;
|
||||
this.col = col;
|
||||
this.dummy = true;
|
||||
}
|
||||
|
||||
public AbstractTableWriterModelCell(AbstractTableWriterModel table, int row, int col, Tc tc, Node content) {
|
||||
this(table, row, col);
|
||||
this.dummy = false;
|
||||
this.content = content;
|
||||
this.tcPr = tc.getTcPr();
|
||||
if (content == null) {
|
||||
logger.error("No content for row " + row + ", col " + col + "\n" + XmlUtils.marshaltoString(tc, true, true));
|
||||
} else {
|
||||
logger.debug("Cell content: " + XmlUtils.w3CDomNodeToString(content));
|
||||
}
|
||||
try {
|
||||
String vm = tc.getTcPr().getVMerge().getVal();
|
||||
if (vm == null || vm.equals("continue"))
|
||||
this.dummy = true;
|
||||
incrementRowSpan();
|
||||
} catch (NullPointerException ne) {}
|
||||
if (this.dummy) {
|
||||
this.colspan = (table.getCell(row - 1, col)).colspan;
|
||||
} else {
|
||||
try {
|
||||
int gridSpan = tc.getTcPr().getGridSpan().getVal().intValue();
|
||||
this.colspan = gridSpan;
|
||||
} catch (NullPointerException ne) {}
|
||||
}
|
||||
}
|
||||
|
||||
public int getExtraCols() {
|
||||
if (this.colspan < 2)
|
||||
return 0;
|
||||
return this.colspan - 1;
|
||||
}
|
||||
|
||||
public int getExtraRows() {
|
||||
if (this.rowspan > 1)
|
||||
return this.rowspan - 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean isDummy() {
|
||||
return this.dummy;
|
||||
}
|
||||
|
||||
public Node getContent() {
|
||||
return this.content;
|
||||
}
|
||||
|
||||
public int getColumn() {
|
||||
return this.col;
|
||||
}
|
||||
|
||||
protected void incrementRowSpan() {
|
||||
if (this.dummy) {
|
||||
this.table.getCell(this.row - 1, this.col).incrementRowSpan();
|
||||
} else {
|
||||
this.rowspan++;
|
||||
}
|
||||
}
|
||||
|
||||
public String debugStr() {
|
||||
String s = null;
|
||||
if (this.dummy) {
|
||||
s = "d";
|
||||
} else {
|
||||
s = "r";
|
||||
}
|
||||
s = s + "(" + this.row + "," + this.col + ")";
|
||||
s = s + this.colspan;
|
||||
s = s + this.rowspan;
|
||||
return s + " ";
|
||||
}
|
||||
|
||||
public boolean isVMerged() {
|
||||
return (this.tcPr != null && this.tcPr.getVMerge() != null);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package org.docx4j.convert.out.common.writer;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
import org.docx4j.wml.CTTblPrEx;
|
||||
import org.docx4j.wml.Tr;
|
||||
import org.docx4j.wml.TrPr;
|
||||
|
||||
public class AbstractTableWriterModelRow {
|
||||
public AbstractTableWriterModelRow(Tr tr) {
|
||||
this.trPr = tr.getTrPr();
|
||||
this.tblPrEx = tr.getTblPrEx();
|
||||
}
|
||||
|
||||
private List<AbstractTableWriterModelCell> rowContents = new Vector<AbstractTableWriterModelCell>();
|
||||
|
||||
private TrPr trPr;
|
||||
|
||||
private CTTblPrEx tblPrEx;
|
||||
|
||||
public TrPr getRowProperties() {
|
||||
return this.trPr;
|
||||
}
|
||||
|
||||
public CTTblPrEx getRowPropertiesExceptions() {
|
||||
return this.tblPrEx;
|
||||
}
|
||||
|
||||
public List<AbstractTableWriterModelCell> getRowContents() {
|
||||
return this.rowContents;
|
||||
}
|
||||
|
||||
public void add(AbstractTableWriterModelCell newCell) {
|
||||
this.rowContents.add(newCell);
|
||||
}
|
||||
|
||||
public AbstractTableWriterModelCell get(int i) {
|
||||
return this.rowContents.get(i);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return this.rowContents.size();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
package org.docx4j.convert.out.common.writer;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.convert.out.common.AbstractWmlConversionContext;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
public class HyperlinkUtil {
|
||||
private static final Logger log = LoggerFactory.getLogger(HyperlinkUtil.class);
|
||||
|
||||
public static final int HTML_OUTPUT = 1;
|
||||
|
||||
public static final int FO_OUTPUT = 2;
|
||||
|
||||
public static Node toNode(int outputType, AbstractWmlConversionContext context, AbstractHyperlinkWriterModel model, Node content, Document doc) throws TransformerException {
|
||||
Node ret = content;
|
||||
try {
|
||||
context.handleHyperlink(model);
|
||||
switch (outputType) {
|
||||
case 1:
|
||||
ret = toHtmlNode(context, model, content, doc);
|
||||
break;
|
||||
case 2:
|
||||
ret = toFoNode(context, model, content, doc);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid output type: " + outputType);
|
||||
}
|
||||
XmlUtils.treeCopy(content.getChildNodes(), ret);
|
||||
} catch (Docx4JException e) {
|
||||
log.error("Excetion handling the hyperlinkModel: " + model, (Throwable)e);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static Node toFoNode(AbstractWmlConversionContext context, AbstractHyperlinkWriterModel model, Node content, Document doc) {
|
||||
Element ret = doc.createElementNS("http://www.w3.org/1999/XSL/Format", "fo:basic-link");
|
||||
String internalTarget = model.getInternalTarget();
|
||||
String externalTarget = model.getExternalTarget();
|
||||
if (internalTarget == null && externalTarget == null)
|
||||
log.error("No targets found for ");
|
||||
String location = null;
|
||||
if (model.isExternal()) {
|
||||
location = externalTarget;
|
||||
if (internalTarget != null && internalTarget.length() > 0)
|
||||
location = location + "#" + internalTarget;
|
||||
location = "url(" + location + ")";
|
||||
ret.setAttribute("external-destination", location);
|
||||
} else {
|
||||
ret.setAttribute("internal-destination", internalTarget);
|
||||
}
|
||||
if (model.getTooltip() != null && model.getTooltip().length() > 0)
|
||||
ret.setAttribute("role", model.getTooltip());
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static Node toHtmlNode(AbstractWmlConversionContext context, AbstractHyperlinkWriterModel model, Node content, Document doc) {
|
||||
Element ret = doc.createElement("a");
|
||||
String internalTarget = model.getInternalTarget();
|
||||
String externalTarget = model.getExternalTarget();
|
||||
String location = null;
|
||||
if (model.isExternal()) {
|
||||
location = externalTarget;
|
||||
if (internalTarget != null && internalTarget.length() > 0)
|
||||
location = location + "#" + internalTarget;
|
||||
ret.setAttribute("href", location);
|
||||
} else {
|
||||
ret.setAttribute("href", "#" + internalTarget);
|
||||
}
|
||||
if (model.getTgtFrame() != null && model.getTgtFrame().length() > 0)
|
||||
ret.setAttribute("target", model.getTgtFrame());
|
||||
if (model.getTooltip() != null && model.getTooltip().length() > 0)
|
||||
ret.setAttribute("alt", model.getTooltip());
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package org.docx4j.convert.out.common.writer;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.docx4j.convert.out.common.AbstractWmlConversionContext;
|
||||
import org.docx4j.model.fields.FldSimpleModel;
|
||||
import org.docx4j.model.fields.FormattingSwitchHelper;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
public class RefHandler implements AbstractFldSimpleWriter.FldSimpleNodeWriterHandler {
|
||||
protected int outputType = -1;
|
||||
|
||||
public RefHandler(int outputType) {
|
||||
this.outputType = outputType;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "REF";
|
||||
}
|
||||
|
||||
public int getProcessType() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Node toNode(AbstractWmlConversionContext context, FldSimpleModel model, Document doc) throws TransformerException {
|
||||
Node ret = model.getContent();
|
||||
AbstractHyperlinkWriterModel hyperlinkModel = null;
|
||||
if (FormattingSwitchHelper.hasSwitch("\\h", model.getFldParameters())) {
|
||||
hyperlinkModel = new AbstractHyperlinkWriterModel();
|
||||
hyperlinkModel.build(context, model, model.getContent());
|
||||
ret = HyperlinkUtil.toNode(this.outputType, context, hyperlinkModel, model.getContent(), doc);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,258 @@
|
|||
package org.docx4j.convert.out.flatOpcXml;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.convert.out.Output;
|
||||
import org.docx4j.jaxb.Context;
|
||||
import org.docx4j.jaxb.NamespacePrefixMapperUtils;
|
||||
import org.docx4j.openpackaging.URIHelper;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.openpackaging.packages.OpcPackage;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.openpackaging.parts.CustomXmlDataStoragePart;
|
||||
import org.docx4j.openpackaging.parts.JaxbXmlPart;
|
||||
import org.docx4j.openpackaging.parts.Part;
|
||||
import org.docx4j.openpackaging.parts.PartName;
|
||||
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPart;
|
||||
import org.docx4j.openpackaging.parts.XmlPart;
|
||||
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
|
||||
import org.docx4j.relationships.Relationship;
|
||||
import org.docx4j.xmlPackage.ObjectFactory;
|
||||
import org.docx4j.xmlPackage.Package;
|
||||
import org.docx4j.xmlPackage.XmlData;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
public class FlatOpcXmlCreator implements Output {
|
||||
private static Logger log = LoggerFactory.getLogger(FlatOpcXmlCreator.class);
|
||||
|
||||
public OpcPackage packageIn;
|
||||
|
||||
public FlatOpcXmlCreator(OpcPackage p) {
|
||||
this.packageIn = p;
|
||||
}
|
||||
|
||||
private HashMap<String, String> handled = new HashMap<String, String>();
|
||||
|
||||
private static ObjectFactory factory = new ObjectFactory();
|
||||
|
||||
private Package pkgResult;
|
||||
|
||||
public Package get() throws Docx4JException {
|
||||
try {
|
||||
this.pkgResult = factory.createPackage();
|
||||
RelationshipsPart rp = this.packageIn.getRelationshipsPart();
|
||||
saveRawXmlPart(rp);
|
||||
addPartsFromRelationships(rp);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
if (e instanceof Docx4JException)
|
||||
throw (Docx4JException)e;
|
||||
throw new Docx4JException("Failed to save package", e);
|
||||
}
|
||||
log.info("...Done!");
|
||||
return this.pkgResult;
|
||||
}
|
||||
|
||||
public void marshal(OutputStream os) throws Docx4JException {
|
||||
if (this.pkgResult == null) {
|
||||
if (this.packageIn == null)
|
||||
throw new Docx4JException("No zipped package to convert to Flat OPC Package");
|
||||
get();
|
||||
}
|
||||
try {
|
||||
JAXBContext jc = Context.jcXmlPackage;
|
||||
Marshaller marshaller = jc.createMarshaller();
|
||||
marshaller.setProperty("jaxb.formatted.output", Boolean.TRUE);
|
||||
NamespacePrefixMapperUtils.setProperty(marshaller, NamespacePrefixMapperUtils.getPrefixMapper());
|
||||
marshaller.marshal(this.pkgResult, os);
|
||||
} catch (JAXBException e) {
|
||||
throw new Docx4JException("Couldn't marshall Flat OPC Package", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void saveRawXmlPart(Part part) throws Docx4JException {
|
||||
org.docx4j.xmlPackage.Part partResult = createRawXmlPart(part);
|
||||
this.pkgResult.getPart().add(partResult);
|
||||
}
|
||||
|
||||
public static org.docx4j.xmlPackage.Part createRawXmlPart(Part part) throws Docx4JException {
|
||||
String partName = part.getPartName().getName();
|
||||
org.docx4j.xmlPackage.Part partResult = factory.createPart();
|
||||
if (partName.startsWith("/")) {
|
||||
partResult.setName(partName);
|
||||
} else {
|
||||
partResult.setName("/" + partName);
|
||||
}
|
||||
String ct = part.getContentType();
|
||||
if (ct == null) {
|
||||
log.error("Content type not set! ");
|
||||
} else {
|
||||
partResult.setContentType(ct);
|
||||
}
|
||||
XmlData dataResult = factory.createXmlData();
|
||||
partResult.setXmlData(dataResult);
|
||||
Document w3cDoc = null;
|
||||
if (part instanceof JaxbXmlPart) {
|
||||
try {
|
||||
w3cDoc = XmlUtils.getNewDocumentBuilder().newDocument();
|
||||
((JaxbXmlPart)part).marshal(w3cDoc, NamespacePrefixMapperUtils.getPrefixMapper());
|
||||
dataResult.setAny(w3cDoc.getDocumentElement());
|
||||
log.info("PUT SUCCESS: " + partName);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error("Problem saving part " + partName, (Throwable)e);
|
||||
throw new Docx4JException("Problem saving part " + partName, e);
|
||||
}
|
||||
} else if (part instanceof CustomXmlDataStoragePart) {
|
||||
try {
|
||||
dataResult.setAny(((CustomXmlDataStoragePart)part).getData().getDocument().getDocumentElement());
|
||||
log.info("PUT SUCCESS: " + partName);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error("Problem saving part " + partName, (Throwable)e);
|
||||
throw new Docx4JException("Problem saving part " + partName, e);
|
||||
}
|
||||
} else if (part instanceof XmlPart) {
|
||||
Document doc = ((XmlPart)part).getDocument();
|
||||
dataResult.setAny(doc.getDocumentElement());
|
||||
} else {
|
||||
log.error("PROBLEM - No suitable part found for: " + partName);
|
||||
}
|
||||
return partResult;
|
||||
}
|
||||
|
||||
public void addPartsFromRelationships(RelationshipsPart rp) throws Docx4JException {
|
||||
for (Relationship r : rp.getRelationships().getRelationship()) {
|
||||
log.info("For Relationship Id=" + r.getId() + " Source is " + rp.getSourceP().getPartName() + ", Target is " + r.getTarget());
|
||||
if (r.getTargetMode() != null && r.getTargetMode().equals("External")) {
|
||||
log.warn("Encountered external resource " + r.getTarget() + " of type " + r.getType());
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
String resolvedPartUri = URIHelper.resolvePartUri(rp.getSourceURI(), new URI(r.getTarget())).toString();
|
||||
resolvedPartUri = resolvedPartUri.substring(1);
|
||||
log.info("Getting part /" + resolvedPartUri);
|
||||
Part part = this.packageIn.getParts().get(new PartName("/" + resolvedPartUri));
|
||||
if (part == null) {
|
||||
log.error("Part " + resolvedPartUri + " not found!");
|
||||
} else {
|
||||
log.info(part.getClass().getName());
|
||||
}
|
||||
savePart(part);
|
||||
} catch (Exception e) {
|
||||
throw new Docx4JException("Failed to add parts from relationships", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void savePart(Part part) throws Docx4JException, IOException {
|
||||
String resolvedPartUri = part.getPartName().getName().substring(1);
|
||||
if (this.handled.get(resolvedPartUri) != null) {
|
||||
log.debug(".. duplicate save avoided ..");
|
||||
return;
|
||||
}
|
||||
if (part instanceof BinaryPart) {
|
||||
log.info(".. saving binary stuff");
|
||||
saveRawBinaryPart(part);
|
||||
} else {
|
||||
log.info(".. saving ");
|
||||
saveRawXmlPart(part);
|
||||
}
|
||||
this.handled.put(resolvedPartUri, resolvedPartUri);
|
||||
if (part.getRelationshipsPart() != null && part.getRelationshipsPart().getJaxbElement() != null && part.getRelationshipsPart().getJaxbElement().getRelationship() != null && part.getRelationshipsPart().getJaxbElement().getRelationship().size() > 0) {
|
||||
RelationshipsPart rrp = part.getRelationshipsPart();
|
||||
log.info("Found relationships " + rrp.getPartName());
|
||||
String relPart = PartName.getRelationshipsPartName(resolvedPartUri);
|
||||
log.info("Cf constructed name " + relPart);
|
||||
saveRawXmlPart(rrp);
|
||||
addPartsFromRelationships(rrp);
|
||||
} else {
|
||||
log.info("No relationships for " + resolvedPartUri);
|
||||
}
|
||||
}
|
||||
|
||||
protected void saveRawBinaryPart(Part part) throws Docx4JException {
|
||||
org.docx4j.xmlPackage.Part partResult = createRawBinaryPart(part);
|
||||
this.pkgResult.getPart().add(partResult);
|
||||
}
|
||||
|
||||
public static org.docx4j.xmlPackage.Part createRawBinaryPart(Part part) throws Docx4JException {
|
||||
String resolvedPartUri = part.getPartName().getName();
|
||||
org.docx4j.xmlPackage.Part partResult = factory.createPart();
|
||||
partResult.setName(resolvedPartUri);
|
||||
partResult.setContentType(part.getContentType());
|
||||
try {
|
||||
partResult.setCompression("store");
|
||||
partResult.setBinaryData(((BinaryPart)part).getBytes());
|
||||
} catch (Exception e) {
|
||||
throw new Docx4JException("Failed to put binary part", e);
|
||||
}
|
||||
log.info("PUT SUCCESS: " + resolvedPartUri);
|
||||
return partResult;
|
||||
}
|
||||
|
||||
public static String wrapInXmlPart(String xml, String partName, String contentType) {
|
||||
return "<pkg:part pkg:name=\"" + partName + "\"" + " pkg:contentType=\"" + contentType + "\"" + " xmlns:pkg=\"http://schemas.microsoft.com/office/2006/xmlPackage\">" + "<pkg:xmlData>" + xml + "</pkg:xmlData>" + "</pkg:part>";
|
||||
}
|
||||
|
||||
public static String wrapInBinaryPart(byte[] base64, String partName, String contentType) {
|
||||
try {
|
||||
return "<pkg:part pkg:name=\"" + partName + "\"" + " pkg:contentType=\"" + contentType + "\"" + " xmlns:pkg=\"http://schemas.microsoft.com/office/2006/xmlPackage\">" + "<pkg:binaryData>" + new String(base64, "UTF-8") + "</pkg:binaryData>" + "</pkg:part>";
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
log.error(e.getMessage(), (Throwable)e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Document getFlatDomDocument(WordprocessingMLPackage wordMLPackage) throws Docx4JException {
|
||||
Document doc;
|
||||
FlatOpcXmlCreator worker = new FlatOpcXmlCreator(wordMLPackage);
|
||||
Package pkg = worker.get();
|
||||
try {
|
||||
JAXBContext jc = Context.jcXmlPackage;
|
||||
Marshaller marshaller = jc.createMarshaller();
|
||||
doc = XmlUtils.neww3cDomDocument();
|
||||
marshaller.marshal(pkg, doc);
|
||||
} catch (JAXBException e) {
|
||||
throw new Docx4JException("Couldn't marshal Flat OPC to DOM", e);
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
public void output(Result result) throws Docx4JException {
|
||||
TransformerFactory tfactory = XmlUtils.getTransformerFactory();
|
||||
try {
|
||||
Transformer serializer = tfactory.newTransformer();
|
||||
serializer.setOutputProperty("omit-xml-declaration", "yes");
|
||||
serializer.transform(new DOMSource(getFlatDomDocument((WordprocessingMLPackage)this.packageIn)), result);
|
||||
} catch (Exception e) {
|
||||
throw new Docx4JException("Failed to create Flat OPC output", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String inputfilepath = System.getProperty("user.dir") + "/ole_tests/wmv_CT.pptx";
|
||||
OpcPackage wordMLPackage = OpcPackage.load(new File(inputfilepath));
|
||||
FlatOpcXmlCreator worker = new FlatOpcXmlCreator(wordMLPackage);
|
||||
Package result = worker.get();
|
||||
boolean suppressDeclaration = true;
|
||||
boolean prettyprint = true;
|
||||
String data = XmlUtils.marshaltoString(result, suppressDeclaration, prettyprint, Context.jcXmlPackage);
|
||||
FileUtils.writeStringToFile(new File(System.getProperty("user.dir") + "/ole_tests/wmv_CT.xml"), data);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
package org.docx4j.convert.out.fo;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.docx4j.convert.out.AbstractConversionSettings;
|
||||
import org.docx4j.convert.out.FORenderer;
|
||||
import org.docx4j.convert.out.FOSettings;
|
||||
import org.docx4j.convert.out.common.AbstractConversionContext;
|
||||
import org.docx4j.convert.out.common.AbstractExporterDelegate;
|
||||
import org.docx4j.convert.out.common.AbstractWmlExporter;
|
||||
import org.docx4j.convert.out.common.ConversionSectionWrapper;
|
||||
import org.docx4j.convert.out.common.ConversionSectionWrappers;
|
||||
import org.docx4j.model.fields.FormattingSwitchHelper;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.openpackaging.packages.OpcPackage;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class AbstractFOExporter extends AbstractWmlExporter<FOSettings, FOConversionContext> {
|
||||
private static Logger log = LoggerFactory.getLogger(AbstractFOExporter.class);
|
||||
|
||||
protected static final int DEFAULT_START_SIZE = 10240;
|
||||
|
||||
protected AbstractFOExporter(AbstractExporterDelegate<FOSettings, FOConversionContext> exporterDelegate) {
|
||||
super(exporterDelegate);
|
||||
}
|
||||
|
||||
protected static class FoSectionPageInformation implements FORenderer.SectionPageInformation {
|
||||
protected String documentPageCountID = null;
|
||||
|
||||
protected String documentPageCountFoFormat = null;
|
||||
|
||||
protected String sectionPageCountID = null;
|
||||
|
||||
protected String sectionPageCountFoFormat = null;
|
||||
|
||||
public FoSectionPageInformation(String documentPageCountID, String documentPageCountFoFormat, String sectionPageCountID, String sectionPageCountFoFormat) {
|
||||
this.documentPageCountID = documentPageCountID;
|
||||
this.documentPageCountFoFormat = documentPageCountFoFormat;
|
||||
this.sectionPageCountID = sectionPageCountID;
|
||||
this.sectionPageCountFoFormat = sectionPageCountFoFormat;
|
||||
}
|
||||
|
||||
public String getDocumentPageCountID() {
|
||||
return this.documentPageCountID;
|
||||
}
|
||||
|
||||
public String getDocumentPageCountFoFormat() {
|
||||
return this.documentPageCountFoFormat;
|
||||
}
|
||||
|
||||
public String getSectionPageCountID() {
|
||||
return this.sectionPageCountID;
|
||||
}
|
||||
|
||||
public String getSectionPageCountFoFormat() {
|
||||
return this.sectionPageCountFoFormat;
|
||||
}
|
||||
}
|
||||
|
||||
protected FOConversionContext createContext(FOSettings conversionSettings, WordprocessingMLPackage preprocessedPackage, ConversionSectionWrappers sectionWrappers) {
|
||||
return new FOConversionContext(conversionSettings, preprocessedPackage, sectionWrappers);
|
||||
}
|
||||
|
||||
protected OutputStream createIntermediateOutputStream(OutputStream outputStream) throws Docx4JException {
|
||||
return new ByteArrayOutputStream(10240);
|
||||
}
|
||||
|
||||
protected void postprocess(FOSettings conversionSettings, AbstractConversionContext conversionContext, OutputStream intermediateOutputStream, OutputStream outputStream) throws Docx4JException {
|
||||
String foDocument = null;
|
||||
File dumpFoFile = conversionSettings.getFoDumpFile();
|
||||
FOConversionContext foConversionContext = (FOConversionContext)conversionContext;
|
||||
try {
|
||||
foDocument = ((ByteArrayOutputStream)intermediateOutputStream).toString("UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
foDocument = ((ByteArrayOutputStream)intermediateOutputStream).toString();
|
||||
}
|
||||
if (log.isDebugEnabled())
|
||||
log.debug(foDocument);
|
||||
if (dumpFoFile != null)
|
||||
try {
|
||||
FileUtils.writeStringToFile(dumpFoFile, foDocument, "UTF-8");
|
||||
log.info("Saved " + dumpFoFile.getPath());
|
||||
} catch (IOException e) {
|
||||
log.warn("fo file couldn't be dumped to " + dumpFoFile.getPath() + ": " + e, (Throwable)e);
|
||||
}
|
||||
foConversionContext.getFORenderer().render(foDocument, conversionSettings, foConversionContext.isRequires2Pass(), createPageNumberInformation(foConversionContext), outputStream);
|
||||
}
|
||||
|
||||
protected List<FORenderer.SectionPageInformation> createPageNumberInformation(FOConversionContext conversionContext) {
|
||||
List<ConversionSectionWrapper> wrapperList = null;
|
||||
List<FORenderer.SectionPageInformation> ret = Collections.EMPTY_LIST;
|
||||
ConversionSectionWrapper section = null;
|
||||
String sectionId = null;
|
||||
String pageFoFormat = null;
|
||||
String pageWordFormat = null;
|
||||
FORenderer.SectionPageInformation pageNumberInformation = null;
|
||||
if (conversionContext.isRequires2Pass()) {
|
||||
wrapperList = conversionContext.getSections().getList();
|
||||
ret = new ArrayList<FORenderer.SectionPageInformation>(wrapperList.size());
|
||||
for (int i = 0; i < wrapperList.size(); i++) {
|
||||
section = wrapperList.get(i);
|
||||
pageWordFormat = section.getPageNumberInformation().getPageFormat();
|
||||
pageFoFormat = FormattingSwitchHelper.getFoPageNumberFormat(pageWordFormat);
|
||||
sectionId = section.getId();
|
||||
if (pageFoFormat == null)
|
||||
pageFoFormat = "1";
|
||||
pageNumberInformation = new FoSectionPageInformation("field_numpages_" + sectionId + "_value", pageFoFormat, "field_sectionpages_" + sectionId + "_value", pageFoFormat);
|
||||
ret.add(pageNumberInformation);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
package org.docx4j.convert.out.fo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import org.docx4j.convert.out.FORenderer;
|
||||
import org.docx4j.utils.FoNumberFormatUtil;
|
||||
|
||||
public class AbstractPlaceholderLookup implements PlaceholderReplacementHandler.PlaceholderLookup {
|
||||
protected static final String PLACEHOLDER_PREFIX = "${";
|
||||
|
||||
protected static final String PLACEHOLDER_SUFFIX = "}";
|
||||
|
||||
protected static final int PLACEHOLDER_PREFIX_LENGTH = "${".length();
|
||||
|
||||
protected static final int PLACEHOLDER_SUFFIX_LENGTH = "}".length();
|
||||
|
||||
protected static final String FIRST_PASS_DUMMY_VALUE = "00";
|
||||
|
||||
protected List<FORenderer.SectionPageInformation> pageNumberInformation = null;
|
||||
|
||||
protected Map<String, String> placeholderValues = new TreeMap<String, String>();
|
||||
|
||||
protected AbstractPlaceholderLookup(List<FORenderer.SectionPageInformation> pageNumberInformation) {
|
||||
this.pageNumberInformation = setupPageNumerInformation(pageNumberInformation);
|
||||
}
|
||||
|
||||
protected List<FORenderer.SectionPageInformation> setupPageNumerInformation(List<FORenderer.SectionPageInformation> pageNumberInformation) {
|
||||
FORenderer.SectionPageInformation item = null;
|
||||
this.placeholderValues.clear();
|
||||
for (int i = 0; i < pageNumberInformation.size(); i++) {
|
||||
item = pageNumberInformation.get(i);
|
||||
putValue(item.getDocumentPageCountID(), "00");
|
||||
putValue(item.getSectionPageCountID(), "00");
|
||||
}
|
||||
return pageNumberInformation;
|
||||
}
|
||||
|
||||
protected void putDocumentPageCount(int pageCount) {
|
||||
String pageCountValue = null;
|
||||
String foFormat = null;
|
||||
String lastFoFormat = null;
|
||||
FORenderer.SectionPageInformation item = null;
|
||||
for (int i = 0; i < this.pageNumberInformation.size(); i++) {
|
||||
item = this.pageNumberInformation.get(i);
|
||||
foFormat = item.getDocumentPageCountFoFormat();
|
||||
if (!foFormat.equals(lastFoFormat)) {
|
||||
pageCountValue = FoNumberFormatUtil.format(pageCount, foFormat);
|
||||
lastFoFormat = foFormat;
|
||||
}
|
||||
putValue(item.getDocumentPageCountID(), pageCountValue);
|
||||
}
|
||||
}
|
||||
|
||||
protected void putSectionPageCount(int sectionIndex, int pageCount) {
|
||||
FORenderer.SectionPageInformation item = this.pageNumberInformation.get(sectionIndex);
|
||||
String pageCountValue = FoNumberFormatUtil.format(pageCount, item.getSectionPageCountFoFormat());
|
||||
this.placeholderValues.put(createPlaceholder(item.getSectionPageCountID()), pageCountValue);
|
||||
}
|
||||
|
||||
protected void putValue(String placeholderID, String value) {
|
||||
this.placeholderValues.put(createPlaceholder(placeholderID), value);
|
||||
}
|
||||
|
||||
protected String createPlaceholder(String placeholderID) {
|
||||
return "${" + placeholderID + "}";
|
||||
}
|
||||
|
||||
public boolean hasPlaceholders(StringBuilder buffer) {
|
||||
return (buffer.indexOf("${") > -1);
|
||||
}
|
||||
|
||||
public void replaceValues(StringBuilder buffer) {
|
||||
int stIdx = buffer.lastIndexOf("${");
|
||||
int enIdx = -1;
|
||||
String value = null;
|
||||
while (stIdx > -1) {
|
||||
enIdx = buffer.indexOf("}", stIdx + PLACEHOLDER_PREFIX_LENGTH);
|
||||
if (enIdx > -1) {
|
||||
enIdx += PLACEHOLDER_SUFFIX_LENGTH;
|
||||
value = this.placeholderValues.get(buffer.substring(stIdx, enIdx));
|
||||
if (value != null)
|
||||
buffer.replace(stIdx, enIdx, value);
|
||||
}
|
||||
stIdx = (stIdx > 0) ? buffer.lastIndexOf("${", stIdx - 1) : -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package org.docx4j.convert.out.fo;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.docx4j.convert.out.common.AbstractWmlConversionContext;
|
||||
import org.docx4j.convert.out.common.Writer;
|
||||
import org.docx4j.convert.out.common.writer.AbstractBookmarkStartWriter;
|
||||
import org.docx4j.wml.CTBookmark;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
public class BookmarkStartWriter extends AbstractBookmarkStartWriter {
|
||||
private static final Logger log = LoggerFactory.getLogger(BookmarkStartWriter.class);
|
||||
|
||||
public Node toNode(AbstractWmlConversionContext context, Object unmarshalledNode, Node modelContent, Writer.TransformState state, Document doc) throws TransformerException {
|
||||
CTBookmark modelData = (CTBookmark)unmarshalledNode;
|
||||
if (modelData.getName().equals("_GoBack"))
|
||||
return null;
|
||||
Element ret = doc.createElementNS("http://www.w3.org/1999/XSL/Format", "fo:inline");
|
||||
ret.setAttribute("id", modelData.getName());
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package org.docx4j.convert.out.fo;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.docx4j.convert.out.common.AbstractWmlConversionContext;
|
||||
import org.docx4j.convert.out.common.Writer;
|
||||
import org.docx4j.convert.out.common.writer.AbstractBrWriter;
|
||||
import org.docx4j.wml.Br;
|
||||
import org.docx4j.wml.STBrType;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
public class BrWriter extends AbstractBrWriter {
|
||||
private static String XSL_FO = "http://www.w3.org/1999/XSL/Format";
|
||||
|
||||
public Node toNode(AbstractWmlConversionContext context, Object unmarshalledNode, Node modelContent, Writer.TransformState state, Document doc) throws TransformerException {
|
||||
Element ret;
|
||||
Br modelData = (Br)unmarshalledNode;
|
||||
if (modelData.getType() != null && modelData.getType().equals(STBrType.PAGE)) {
|
||||
ret = doc.createElementNS(XSL_FO, "block");
|
||||
ret.setAttribute("break-before", "page");
|
||||
} else {
|
||||
ret = doc.createElementNS(XSL_FO, "block");
|
||||
ret.setAttribute("linefeed-treatment", "preserve");
|
||||
ret.setAttribute("white-space-treatment", "preserve");
|
||||
ret.setAttribute("line-height", "0pt");
|
||||
ret.setTextContent("\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
package org.docx4j.convert.out.fo;
|
||||
|
||||
import java.util.List;
|
||||
import org.docx4j.convert.out.AbstractConversionSettings;
|
||||
import org.docx4j.convert.out.FORenderer;
|
||||
import org.docx4j.convert.out.FOSettings;
|
||||
import org.docx4j.convert.out.common.AbstractWmlConversionContext;
|
||||
import org.docx4j.convert.out.common.AbstractWriterRegistry;
|
||||
import org.docx4j.convert.out.common.ConversionSectionWrapper;
|
||||
import org.docx4j.convert.out.common.ConversionSectionWrappers;
|
||||
import org.docx4j.convert.out.common.writer.AbstractMessageWriter;
|
||||
import org.docx4j.convert.out.fo.renderers.FORendererApacheFOP;
|
||||
import org.docx4j.convert.out.fo.renderers.FORendererDummy;
|
||||
import org.docx4j.fonts.RunFontSelector;
|
||||
import org.docx4j.model.images.ConversionImageHandler;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
public class FOConversionContext extends AbstractWmlConversionContext {
|
||||
private static Logger log = LoggerFactory.getLogger(FOConversionContext.class);
|
||||
|
||||
protected boolean requires2PassChecked = false;
|
||||
|
||||
protected boolean requires2Pass = false;
|
||||
|
||||
protected FORenderer foRenderer;
|
||||
|
||||
protected static final AbstractWriterRegistry FO_WRITER_REGISTRY = new AbstractWriterRegistry() {
|
||||
protected void registerDefaultWriterInstances() {
|
||||
registerWriter(new TableWriter());
|
||||
registerWriter(new SymbolWriter());
|
||||
registerWriter(new BrWriter());
|
||||
registerWriter(new FldSimpleWriter());
|
||||
registerWriter(new BookmarkStartWriter());
|
||||
registerWriter(new HyperlinkWriter());
|
||||
registerWriter(new FOPictWriterFloatAvoided());
|
||||
}
|
||||
};
|
||||
|
||||
protected static final AbstractMessageWriter FO_MESSAGE_WRITER = new AbstractMessageWriter() {
|
||||
protected String getOutputPrefix() {
|
||||
return "<fo:block xmlns:fo=\"http://www.w3.org/1999/XSL/Format\" font-size=\"12pt\" color=\"red\" font-family=\"sans-serif\" line-height=\"15pt\" space-after.optimum=\"3pt\" text-align=\"justify\"> ";
|
||||
}
|
||||
|
||||
protected String getOutputSuffix() {
|
||||
return "</fo:block>";
|
||||
}
|
||||
};
|
||||
|
||||
public FOConversionContext(FOSettings settings, WordprocessingMLPackage wmlPackage, ConversionSectionWrappers conversionSectionWrappers) {
|
||||
super(FO_WRITER_REGISTRY, FO_MESSAGE_WRITER, settings, wmlPackage, conversionSectionWrappers, createRunFontSelector(wmlPackage));
|
||||
this.foRenderer = initializeFoRenderer(settings);
|
||||
}
|
||||
|
||||
private static RunFontSelector createRunFontSelector(WordprocessingMLPackage wmlPackage) {
|
||||
return new RunFontSelector(wmlPackage, new RunFontSelector.RunFontCharacterVisitor() {
|
||||
DocumentFragment df;
|
||||
|
||||
StringBuilder sb = new StringBuilder(1024);
|
||||
|
||||
Element span;
|
||||
|
||||
String lastFont;
|
||||
|
||||
String fallbackFontName;
|
||||
|
||||
private Document document;
|
||||
|
||||
public void setDocument(Document document) {
|
||||
this.document = document;
|
||||
this.df = document.createDocumentFragment();
|
||||
}
|
||||
|
||||
private boolean spanReusable = true;
|
||||
|
||||
private RunFontSelector runFontSelector;
|
||||
|
||||
public boolean isReusable() {
|
||||
return this.spanReusable;
|
||||
}
|
||||
|
||||
public void addCharacterToCurrent(char c) {
|
||||
this.sb.append(c);
|
||||
}
|
||||
|
||||
public void finishPrevious() {
|
||||
if (this.sb.length() > 0) {
|
||||
if (this.span == null) {
|
||||
this.span = this.runFontSelector.createElement(this.document);
|
||||
if (this.lastFont != null)
|
||||
this.runFontSelector.setAttribute(this.span, this.lastFont);
|
||||
}
|
||||
this.df.appendChild(this.span);
|
||||
this.span.setTextContent(this.sb.toString());
|
||||
this.sb.setLength(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void createNew() {
|
||||
this.span = this.runFontSelector.createElement(this.document);
|
||||
}
|
||||
|
||||
public void setMustCreateNewFlag(boolean val) {
|
||||
this.spanReusable = !val;
|
||||
}
|
||||
|
||||
public void fontAction(String fontname) {
|
||||
if (fontname == null) {
|
||||
this.runFontSelector.setAttribute(this.span, this.fallbackFontName);
|
||||
} else {
|
||||
this.runFontSelector.setAttribute(this.span, fontname);
|
||||
this.lastFont = fontname;
|
||||
}
|
||||
}
|
||||
|
||||
public Object getResult() {
|
||||
this.span = null;
|
||||
return this.df;
|
||||
}
|
||||
|
||||
public void setRunFontSelector(RunFontSelector runFontSelector) {
|
||||
this.runFontSelector = runFontSelector;
|
||||
}
|
||||
|
||||
public void setFallbackFont(String fontname) {
|
||||
this.fallbackFontName = fontname;
|
||||
}
|
||||
}, RunFontSelector.RunFontActionType.XSL_FO);
|
||||
}
|
||||
|
||||
protected FORenderer initializeFoRenderer(FOSettings settings) {
|
||||
FORenderer ret = settings.getCustomFoRenderer();
|
||||
if (ret == null) {
|
||||
if ("application/xml-fo".equals(settings.getApacheFopMime())) {
|
||||
ret = FORendererDummy.getInstance();
|
||||
forceRequires1Pass();
|
||||
} else {
|
||||
ret = FORendererApacheFOP.getInstance();
|
||||
}
|
||||
settings.setCustomFoRenderer(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected ConversionImageHandler initializeImageHandler(AbstractConversionSettings settings, ConversionImageHandler handler) {
|
||||
if (handler == null)
|
||||
handler = (settings.getImageDirPath() != null) ? new FOConversionImageHandler(settings.getImageDirPath(), true) : new FOConversionImageHandler();
|
||||
return handler;
|
||||
}
|
||||
|
||||
public FORenderer getFORenderer() {
|
||||
return this.foRenderer;
|
||||
}
|
||||
|
||||
public void forceRequires1Pass() {
|
||||
this.requires2PassChecked = true;
|
||||
this.requires2Pass = false;
|
||||
}
|
||||
|
||||
public boolean isRequires2Pass() {
|
||||
if (!this.requires2PassChecked) {
|
||||
this.requires2Pass = checkRequires2Pass();
|
||||
this.requires2PassChecked = true;
|
||||
}
|
||||
return this.requires2Pass;
|
||||
}
|
||||
|
||||
protected boolean checkRequires2Pass() {
|
||||
boolean ret = false;
|
||||
boolean sectionPagesUsed = false;
|
||||
ConversionSectionWrapper wrapper = null;
|
||||
List<ConversionSectionWrapper> wrapperList = getSections().getList();
|
||||
for (int i = 0; !ret && i < wrapperList.size(); i++) {
|
||||
wrapper = wrapperList.get(i);
|
||||
if (wrapper.getPageNumberInformation().getPageStart() > -1)
|
||||
ret = ((i == 0 && wrapper.getPageNumberInformation().getPageStart() != 1) || i > 0);
|
||||
if (wrapper.getPageNumberInformation().isSectionpagesPresent())
|
||||
sectionPagesUsed = true;
|
||||
}
|
||||
return (ret || (sectionPagesUsed && wrapperList.size() > 1));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package org.docx4j.convert.out.fo;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import org.docx4j.model.images.FileConversionImageHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class FOConversionImageHandler extends FileConversionImageHandler {
|
||||
private static final Logger log = LoggerFactory.getLogger(FOConversionImageHandler.class);
|
||||
|
||||
public FOConversionImageHandler() {
|
||||
super(null, true);
|
||||
}
|
||||
|
||||
public FOConversionImageHandler(String imageDirPath, boolean includeUUID) {
|
||||
super(imageDirPath, includeUUID);
|
||||
}
|
||||
|
||||
protected String setupImageUri(File imageFile) {
|
||||
try {
|
||||
return imageFile.toURI().toURL().toString();
|
||||
} catch (MalformedURLException e) {
|
||||
log.error(e.getMessage(), (Throwable)e);
|
||||
return imageFile.getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package org.docx4j.convert.out.fo;
|
||||
|
||||
import org.docx4j.convert.out.FOSettings;
|
||||
import org.docx4j.convert.out.common.Exporter;
|
||||
|
||||
public class FOExporterVisitor extends AbstractFOExporter {
|
||||
protected static final FOExporterVisitorDelegate EXPORTER_DELEGATE_INSTANCE = new FOExporterVisitorDelegate();
|
||||
|
||||
protected static FOExporterVisitor instance = null;
|
||||
|
||||
protected FOExporterVisitor() {
|
||||
super(EXPORTER_DELEGATE_INSTANCE);
|
||||
}
|
||||
|
||||
public static Exporter<FOSettings> getInstance() {
|
||||
if (instance == null)
|
||||
synchronized (FOExporterVisitor.class) {
|
||||
if (instance == null)
|
||||
instance = new FOExporterVisitor();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
package org.docx4j.convert.out.fo;
|
||||
|
||||
import java.util.List;
|
||||
import org.docx4j.convert.out.FOSettings;
|
||||
import org.docx4j.convert.out.common.AbstractVisitorExporterDelegate;
|
||||
import org.docx4j.convert.out.common.AbstractWmlConversionContext;
|
||||
import org.docx4j.convert.out.common.ConversionSectionWrapper;
|
||||
import org.docx4j.convert.out.common.XsltCommonFunctions;
|
||||
import org.docx4j.model.fields.FormattingSwitchHelper;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.openpackaging.parts.Part;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
public class FOExporterVisitorDelegate extends AbstractVisitorExporterDelegate<FOSettings, FOConversionContext> {
|
||||
protected FOExporterVisitorDelegate() {
|
||||
super(FOExporterVisitorGenerator.GENERATOR_FACTORY);
|
||||
}
|
||||
|
||||
private static String XSL_FO = "http://www.w3.org/1999/XSL/Format";
|
||||
|
||||
protected Element createDocumentRoot(FOConversionContext conversionContext, Document document) throws Docx4JException {
|
||||
return document.createElementNS(XSL_FO, "root");
|
||||
}
|
||||
|
||||
protected void appendDocumentHeader(FOConversionContext conversionContext, Document document, Element documentRoot) throws Docx4JException {
|
||||
LayoutMasterSetBuilder.appendLayoutMasterSetFragment(conversionContext, documentRoot);
|
||||
}
|
||||
|
||||
protected Element createSectionRoot(FOConversionContext conversionContext, Document document, ConversionSectionWrapper sectionWrapper, Element currentParent) throws Docx4JException {
|
||||
Element pageSequence = document.createElementNS(XSL_FO, "page-sequence");
|
||||
int pageNumberInitial = sectionWrapper.getPageNumberInformation().getPageStart();
|
||||
String pageFormat = sectionWrapper.getPageNumberInformation().getPageFormat();
|
||||
pageSequence.setAttribute("master-reference", sectionWrapper.getId());
|
||||
pageSequence.setAttribute("id", "section_" + sectionWrapper.getId());
|
||||
pageFormat = FormattingSwitchHelper.getFoPageNumberFormat(pageFormat);
|
||||
if (pageNumberInitial > -1)
|
||||
pageSequence.setAttribute("initial-page-number", Integer.toString(pageNumberInitial));
|
||||
if (pageFormat != null)
|
||||
pageSequence.setAttribute("format", pageFormat);
|
||||
return pageSequence;
|
||||
}
|
||||
|
||||
protected void appendSectionHeader(FOConversionContext conversionContext, Document document, ConversionSectionWrapper sectionWrapper, Element currentParent) throws Docx4JException {
|
||||
Element staticContent = null;
|
||||
if (XsltCommonFunctions.hasFirstHeader(conversionContext))
|
||||
appendPartContent(conversionContext, document, currentParent, "xsl-region-before-firstpage", sectionWrapper.getHeaderFooterPolicy().getFirstHeader(), sectionWrapper.getHeaderFooterPolicy().getFirstHeader().getJaxbElement().getContent());
|
||||
if (XsltCommonFunctions.hasFirstFooter(conversionContext))
|
||||
appendPartContent(conversionContext, document, currentParent, "xsl-region-after-firstpage", sectionWrapper.getHeaderFooterPolicy().getFirstFooter(), sectionWrapper.getHeaderFooterPolicy().getFirstFooter().getJaxbElement().getContent());
|
||||
if (XsltCommonFunctions.hasEvenHeader(conversionContext))
|
||||
appendPartContent(conversionContext, document, currentParent, "xsl-region-before-evenpage", sectionWrapper.getHeaderFooterPolicy().getEvenHeader(), sectionWrapper.getHeaderFooterPolicy().getEvenHeader().getJaxbElement().getContent());
|
||||
if (XsltCommonFunctions.hasEvenFooter(conversionContext))
|
||||
appendPartContent(conversionContext, document, currentParent, "xsl-region-after-evenpage", sectionWrapper.getHeaderFooterPolicy().getEvenFooter(), sectionWrapper.getHeaderFooterPolicy().getEvenFooter().getJaxbElement().getContent());
|
||||
if (XsltCommonFunctions.hasDefaultHeader(conversionContext))
|
||||
appendPartContent(conversionContext, document, currentParent, "xsl-region-before-default", sectionWrapper.getHeaderFooterPolicy().getDefaultHeader(), sectionWrapper.getHeaderFooterPolicy().getDefaultHeader().getJaxbElement().getContent());
|
||||
if (XsltCommonFunctions.hasDefaultFooter(conversionContext))
|
||||
appendPartContent(conversionContext, document, currentParent, "xsl-region-after-default", sectionWrapper.getHeaderFooterPolicy().getDefaultFooter(), sectionWrapper.getHeaderFooterPolicy().getDefaultFooter().getJaxbElement().getContent());
|
||||
}
|
||||
|
||||
protected void appendPartContent(FOConversionContext conversionContext, Document document, Element currentParent, String name, Part part, List<Object> content) throws Docx4JException {
|
||||
Element flow = document.createElementNS(XSL_FO, "static-content");
|
||||
currentParent.appendChild(flow);
|
||||
flow.setAttribute("flow-name", name);
|
||||
appendPartContent(conversionContext, document, part, content, flow);
|
||||
}
|
||||
|
||||
protected Element createSectionBody(FOConversionContext conversionContext, Document document, ConversionSectionWrapper sectionWrapper, Element currentParent) throws Docx4JException {
|
||||
Element ret = document.createElementNS(XSL_FO, "flow");
|
||||
ret.setAttribute("flow-name", "xsl-region-body");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,337 @@
|
|||
package org.docx4j.convert.out.fo;
|
||||
|
||||
import java.util.List;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.convert.out.common.AbstractVisitorExporterDelegate;
|
||||
import org.docx4j.convert.out.common.AbstractVisitorExporterGenerator;
|
||||
import org.docx4j.convert.out.common.AbstractWmlConversionContext;
|
||||
import org.docx4j.model.PropertyResolver;
|
||||
import org.docx4j.model.images.WordXmlPictureE10;
|
||||
import org.docx4j.model.images.WordXmlPictureE20;
|
||||
import org.docx4j.model.listnumbering.Emulator;
|
||||
import org.docx4j.model.properties.Property;
|
||||
import org.docx4j.model.properties.PropertyFactory;
|
||||
import org.docx4j.model.properties.paragraph.Indent;
|
||||
import org.docx4j.model.properties.paragraph.PShading;
|
||||
import org.docx4j.model.styles.StyleUtil;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.wml.Br;
|
||||
import org.docx4j.wml.CTTabStop;
|
||||
import org.docx4j.wml.JcEnumeration;
|
||||
import org.docx4j.wml.P;
|
||||
import org.docx4j.wml.PPr;
|
||||
import org.docx4j.wml.PPrBase;
|
||||
import org.docx4j.wml.R;
|
||||
import org.docx4j.wml.RPr;
|
||||
import org.docx4j.wml.STBrType;
|
||||
import org.docx4j.wml.STTabJc;
|
||||
import org.docx4j.wml.STTabTlc;
|
||||
import org.docx4j.wml.Style;
|
||||
import org.docx4j.wml.TcPr;
|
||||
import org.docx4j.wml.TrPr;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.DOMException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
public class FOExporterVisitorGenerator extends AbstractVisitorExporterGenerator<FOConversionContext> {
|
||||
private static Logger log = LoggerFactory.getLogger(FOExporterVisitorGenerator.class);
|
||||
|
||||
private static String XSL_FO = "http://www.w3.org/1999/XSL/Format";
|
||||
|
||||
public static final AbstractVisitorExporterDelegate.AbstractVisitorExporterGeneratorFactory<FOConversionContext> GENERATOR_FACTORY = new AbstractVisitorExporterDelegate.AbstractVisitorExporterGeneratorFactory<FOConversionContext>() {
|
||||
public AbstractVisitorExporterGenerator<FOConversionContext> createInstance(FOConversionContext conversionContext, Document document, Node parentNode) {
|
||||
return new FOExporterVisitorGenerator(conversionContext, document, parentNode);
|
||||
}
|
||||
};
|
||||
|
||||
private FOExporterVisitorGenerator(FOConversionContext conversionContext, Document document, Node parentNode) {
|
||||
super(conversionContext, document, parentNode);
|
||||
}
|
||||
|
||||
protected AbstractVisitorExporterDelegate.AbstractVisitorExporterGeneratorFactory<FOConversionContext> getFactory() {
|
||||
return GENERATOR_FACTORY;
|
||||
}
|
||||
|
||||
protected DocumentFragment createImage(int imgType, FOConversionContext conversionContext, Object anchorOrInline) {
|
||||
switch (imgType) {
|
||||
case 1:
|
||||
return WordXmlPictureE10.createXslFoImgE10(conversionContext, anchorOrInline);
|
||||
case 2:
|
||||
return WordXmlPictureE20.createXslFoImgE20(conversionContext, anchorOrInline);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Element createNode(Document doc, int nodeType) {
|
||||
switch (nodeType) {
|
||||
case 1:
|
||||
return this.document.createElementNS(XSL_FO, "block");
|
||||
case 2:
|
||||
return this.document.createElementNS(XSL_FO, "inline");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void handleBr(Br br) {
|
||||
boolean firstBr = true;
|
||||
R r = (R)br.getParent();
|
||||
int pos = getPos(r.getContent(), br);
|
||||
if (pos < 0) {
|
||||
log.error("Couldn't locate w:br in w:r");
|
||||
} else if (pos == 0) {
|
||||
Object rParent = r.getParent();
|
||||
if (rParent instanceof P) {
|
||||
P parentP = (P)rParent;
|
||||
pos = getPos(parentP.getContent(), r);
|
||||
if (pos < 0) {
|
||||
log.error("Couldn't locate w:r in w:p");
|
||||
} else if (pos > 0) {
|
||||
Object beforeR = parentP.getContent().get(pos - 1);
|
||||
if (beforeR instanceof R) {
|
||||
List<Object> list = ((R)beforeR).getContent();
|
||||
Object previous = list.get(list.size() - 1);
|
||||
if (previous instanceof Br)
|
||||
firstBr = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.info("TODO: handle run parent " + rParent.getClass().getName());
|
||||
}
|
||||
} else {
|
||||
Object previous = r.getContent().get(pos - 1);
|
||||
if (previous instanceof Br)
|
||||
firstBr = false;
|
||||
}
|
||||
if (!firstBr && (br.getType() == null || br.getType().equals(STBrType.TEXT_WRAPPING))) {
|
||||
Element ret = createNode(this.document, 1);
|
||||
ret.setAttribute("linefeed-treatment", "preserve");
|
||||
ret.setAttribute("white-space-treatment", "preserve");
|
||||
ret.setTextContent("\n");
|
||||
getCurrentParent().appendChild(ret);
|
||||
} else {
|
||||
convertToNode(this.conversionContext, br, "w:br", this.document, getCurrentParent());
|
||||
}
|
||||
if (br.getType() != null && br.getType().equals(STBrType.PAGE))
|
||||
this.currentSpan = null;
|
||||
}
|
||||
|
||||
protected void convertTabToNode(FOConversionContext conversionContext, Document document) throws DOMException {
|
||||
if (!conversionContext.isInComplexFieldDefinition())
|
||||
if (this.pPr != null && this.pPr.getTabs() != null) {
|
||||
CTTabStop tabStop = this.pPr.getTabs().getTab().get(0);
|
||||
if (tabStop != null && tabStop.getLeader().equals(STTabTlc.DOT) && tabStop.getVal().equals(STTabJc.RIGHT)) {
|
||||
Element foLeader = document.createElementNS(XSL_FO, "leader");
|
||||
foLeader.setAttribute("leader-length.minimum", "12pt");
|
||||
foLeader.setAttribute("leader-length.maximum", "100%");
|
||||
foLeader.setAttribute("leader-length.optimum", "40pt");
|
||||
foLeader.setAttribute("leader-pattern", "dots");
|
||||
getCurrentParent().appendChild(foLeader);
|
||||
} else {
|
||||
getCurrentParent().appendChild(document.createTextNode(" "));
|
||||
}
|
||||
} else {
|
||||
getCurrentParent().appendChild(document.createTextNode(" "));
|
||||
}
|
||||
}
|
||||
|
||||
protected Element handlePPr(FOConversionContext conversionContext, PPr pPrDirect, boolean sdt, Element currentParent) {
|
||||
Element ret = currentParent;
|
||||
PropertyResolver propertyResolver = conversionContext.getPropertyResolver();
|
||||
String defaultParagraphStyleId = "Normal";
|
||||
if (conversionContext.getWmlPackage().getMainDocumentPart().getStyleDefinitionsPart(false) != null) {
|
||||
Style defaultParagraphStyle = conversionContext.getWmlPackage().getMainDocumentPart().getStyleDefinitionsPart(false).getDefaultParagraphStyle();
|
||||
if (defaultParagraphStyle != null)
|
||||
defaultParagraphStyleId = defaultParagraphStyle.getStyleId();
|
||||
}
|
||||
String pStyleVal = null;
|
||||
if (pPrDirect != null && pPrDirect.getPStyle() != null) {
|
||||
pStyleVal = pPrDirect.getPStyle().getVal();
|
||||
} else {
|
||||
pStyleVal = defaultParagraphStyleId;
|
||||
}
|
||||
getLog().debug("style '" + pStyleVal);
|
||||
try {
|
||||
this.pPr = propertyResolver.getEffectivePPr(pPrDirect);
|
||||
getLog().debug("getting rPr for paragraph style");
|
||||
this.rPr = propertyResolver.getEffectiveRPr(null, pPrDirect);
|
||||
RPr rPrParagraphMark = XmlUtils.<RPr>deepCopy(this.rPr);
|
||||
if (pPrDirect != null)
|
||||
StyleUtil.apply(pPrDirect.getRPr(), rPrParagraphMark);
|
||||
if (getLog().isDebugEnabled() && this.pPr != null)
|
||||
getLog().debug(XmlUtils.marshaltoString(this.pPr, true, true));
|
||||
boolean inlist = false;
|
||||
boolean indentHandledByNumbering = false;
|
||||
Element foBlockElement = null;
|
||||
Element foListBlock = null;
|
||||
if (this.pPr != null && this.pPr.getNumPr() != null && this.pPr.getNumPr().getNumId() != null && this.pPr.getNumPr().getNumId().getVal().longValue() != 0L) {
|
||||
Emulator.ResultTriple triple;
|
||||
inlist = true;
|
||||
foListBlock = this.document.createElementNS(XSL_FO, "list-block");
|
||||
currentParent.appendChild(foListBlock);
|
||||
if (this.pPr.getShd() != null) {
|
||||
PShading pShading = new PShading(this.pPr.getShd());
|
||||
pShading.setXslFO(foListBlock);
|
||||
}
|
||||
Element foListItem = this.document.createElementNS(XSL_FO, "list-item");
|
||||
foListBlock.appendChild(foListItem);
|
||||
Element foListItemLabel = this.document.createElementNS(XSL_FO, "list-item-label");
|
||||
foListItem.appendChild(foListItemLabel);
|
||||
Element foListItemLabelBody = this.document.createElementNS(XSL_FO, "block");
|
||||
foListItemLabel.appendChild(foListItemLabelBody);
|
||||
Element foListItemBody = this.document.createElementNS("http://www.w3.org/1999/XSL/Format", "fo:list-item-body");
|
||||
foListItem.appendChild(foListItemBody);
|
||||
foListItemBody.setAttribute("start-indent", "body-start()");
|
||||
if (pPrDirect != null && pPrDirect.getNumPr() != null) {
|
||||
triple = Emulator.getNumber(conversionContext.getWmlPackage(), pStyleVal, pPrDirect.getNumPr().getNumId().getVal().toString(), pPrDirect.getNumPr().getIlvl().getVal().toString());
|
||||
} else {
|
||||
PPrBase.NumPr.Ilvl ilvl = this.pPr.getNumPr().getIlvl();
|
||||
String ilvlString = (ilvl == null) ? "0" : ilvl.getVal().toString();
|
||||
triple = null;
|
||||
if (this.pPr.getNumPr().getNumId() != null)
|
||||
triple = Emulator.getNumber(conversionContext.getWmlPackage(), pStyleVal, this.pPr.getNumPr().getNumId().getVal().toString(), ilvlString);
|
||||
}
|
||||
if (triple == null) {
|
||||
getLog().warn("computed number ResultTriple was null");
|
||||
if (getLog().isDebugEnabled())
|
||||
foListItemLabelBody.setTextContent("nrt");
|
||||
} else if (triple.getRPr() == null) {
|
||||
if (this.pPr.getRPr() == null) {
|
||||
XsltFOFunctions.setFont(conversionContext, foListItemLabelBody, this.pPr, this.rPr, triple.getNumString());
|
||||
} else {
|
||||
createFoAttributes(conversionContext.getWmlPackage(), rPrParagraphMark, foListItemLabel);
|
||||
createFoAttributes(conversionContext.getWmlPackage(), rPrParagraphMark, foListItemBody);
|
||||
XsltFOFunctions.setFont(conversionContext, foListItemLabelBody, this.pPr, rPrParagraphMark, triple.getNumString());
|
||||
}
|
||||
} else {
|
||||
RPr actual = XmlUtils.<RPr>deepCopy(triple.getRPr());
|
||||
XsltFOFunctions.setFont(conversionContext, foListItemLabelBody, this.pPr, actual, triple.getNumString());
|
||||
StyleUtil.apply(rPrParagraphMark, actual);
|
||||
createFoAttributes(conversionContext.getWmlPackage(), actual, foListItemLabel);
|
||||
createFoAttributes(conversionContext.getWmlPackage(), actual, foListItemBody);
|
||||
}
|
||||
int numChars = 1;
|
||||
if (triple.getBullet() != null) {
|
||||
foListItemLabelBody.setTextContent(triple.getBullet());
|
||||
} else if (triple.getNumString() == null) {
|
||||
getLog().warn("computed NumString was null!");
|
||||
if (getLog().isDebugEnabled())
|
||||
foListItemLabelBody.setTextContent("nns");
|
||||
numChars = 0;
|
||||
} else {
|
||||
Text number = this.document.createTextNode(triple.getNumString());
|
||||
foListItemLabelBody.appendChild(number);
|
||||
numChars = triple.getNumString().length();
|
||||
}
|
||||
Indent indent = new Indent(pPrDirect.getInd(), triple.getIndent());
|
||||
if (indent.isHanging()) {
|
||||
indent.setXslFOListBlock(foListBlock, -1);
|
||||
} else {
|
||||
int numWidth = 90 * numChars;
|
||||
int pdbs = XsltFOFunctions.getDistanceToNextTabStop(conversionContext, indent.getNumberPosition(), numWidth, pPrDirect.getTabs(), conversionContext.getWmlPackage().getMainDocumentPart().getDocumentSettingsPart());
|
||||
indent.setXslFOListBlock(foListBlock, pdbs);
|
||||
}
|
||||
indentHandledByNumbering = true;
|
||||
foBlockElement = this.document.createElementNS(XSL_FO, "block");
|
||||
foListItemBody.appendChild(foBlockElement);
|
||||
ret = foBlockElement;
|
||||
}
|
||||
if (this.pPr != null) {
|
||||
boolean ignoreBorders = !sdt;
|
||||
createFoAttributes(conversionContext, this.pPr, currentParent, inlist, ignoreBorders);
|
||||
}
|
||||
if (this.rPr != null)
|
||||
if (foListBlock == null) {
|
||||
createFoAttributes(conversionContext.getWmlPackage(), this.rPr, currentParent);
|
||||
} else {
|
||||
createFoAttributes(conversionContext.getWmlPackage(), this.rPr, foListBlock);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
getLog().error(e.getMessage(), (Throwable)e);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected void createFoAttributes(FOConversionContext conversionContext, PPr pPr, Element foBlockElement, boolean inList, boolean ignoreBorders) {
|
||||
List<Property> properties = PropertyFactory.createProperties(conversionContext.getWmlPackage(), pPr);
|
||||
for (Property p : properties) {
|
||||
if (p != null) {
|
||||
if (ignoreBorders && (p instanceof org.docx4j.model.properties.paragraph.PBorderTop || p instanceof org.docx4j.model.properties.paragraph.PBorderBottom))
|
||||
continue;
|
||||
if (inList && !(p instanceof Indent)) {
|
||||
p.setXslFO(foBlockElement);
|
||||
continue;
|
||||
}
|
||||
if (!inList)
|
||||
p.setXslFO(foBlockElement);
|
||||
}
|
||||
}
|
||||
if (pPr == null)
|
||||
return;
|
||||
if (pPr.getBidi() != null && pPr.getBidi().isVal())
|
||||
if (pPr.getJc() != null)
|
||||
if (pPr.getJc().getVal().equals(JcEnumeration.RIGHT)) {
|
||||
foBlockElement.setAttribute("text-align", "left");
|
||||
} else if (pPr.getJc().getVal().equals(JcEnumeration.LEFT)) {
|
||||
foBlockElement.setAttribute("text-align", "right");
|
||||
}
|
||||
if (pPr.getTabs() != null) {
|
||||
CTTabStop tabStop = pPr.getTabs().getTab().get(0);
|
||||
if (tabStop != null && tabStop.getVal().equals(STTabJc.RIGHT))
|
||||
foBlockElement.setAttribute("text-align-last", "justify");
|
||||
}
|
||||
}
|
||||
|
||||
protected static void applyFoAttributes(List<Property> properties, Element foElement) {
|
||||
if (properties != null && !properties.isEmpty())
|
||||
for (int i = 0; i < properties.size(); i++)
|
||||
properties.get(i).setXslFO(foElement);
|
||||
}
|
||||
|
||||
protected static void createFoAttributes(TrPr trPr, Element foBlockElement) {
|
||||
if (trPr == null)
|
||||
return;
|
||||
applyFoAttributes(PropertyFactory.createProperties(trPr), foBlockElement);
|
||||
}
|
||||
|
||||
protected static void createFoAttributes(TcPr tcPr, Element foBlockElement) {
|
||||
if (tcPr == null)
|
||||
return;
|
||||
applyFoAttributes(PropertyFactory.createProperties(tcPr), foBlockElement);
|
||||
}
|
||||
|
||||
protected void handleRPr(FOConversionContext conversionContext, PPr pPrDirect, RPr rPrDirect, Element currentParent) {
|
||||
PropertyResolver propertyResolver = conversionContext.getPropertyResolver();
|
||||
try {
|
||||
RPr rPr = propertyResolver.getEffectiveRPr(rPrDirect, pPrDirect);
|
||||
if (getLog().isDebugEnabled() && rPr != null)
|
||||
getLog().debug(XmlUtils.marshaltoString(rPr, true, true));
|
||||
createFoAttributes(conversionContext.getWmlPackage(), rPr, currentParent);
|
||||
} catch (Exception e) {
|
||||
getLog().error(e.getMessage(), (Throwable)e);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void createFoAttributes(WordprocessingMLPackage wmlPackage, RPr rPr, Element foInlineElement) {
|
||||
List<Property> properties = PropertyFactory.createProperties(wmlPackage, rPr);
|
||||
for (Property p : properties)
|
||||
p.setXslFO(foInlineElement);
|
||||
}
|
||||
|
||||
protected void rtlAwareAppendChildToCurrentP(Element spanEl) {
|
||||
if (this.rPr != null && this.rPr.getRtl() != null && this.rPr.getRtl().isVal()) {
|
||||
spanEl.removeAttribute("direction");
|
||||
Element bidiOverride = this.document.createElementNS("http://www.w3.org/1999/XSL/Format", "fo:bidi-override");
|
||||
bidiOverride.setAttribute("unicode-bidi", "embed");
|
||||
bidiOverride.setAttribute("direction", "rtl");
|
||||
bidiOverride.appendChild(spanEl);
|
||||
this.currentP.appendChild(bidiOverride);
|
||||
} else {
|
||||
this.currentP.appendChild(spanEl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package org.docx4j.convert.out.fo;
|
||||
|
||||
import org.docx4j.convert.out.FOSettings;
|
||||
import org.docx4j.convert.out.common.Exporter;
|
||||
import org.docx4j.convert.out.common.WmlXsltExporterDelegate;
|
||||
|
||||
public class FOExporterXslt extends AbstractFOExporter {
|
||||
protected static final String DEFAULT_TEMPLATES_RESOURCE = "org/docx4j/convert/out/fo/docx2fo.xslt";
|
||||
|
||||
protected static final WmlXsltExporterDelegate<FOSettings, FOConversionContext> EXPORTER_DELEGATE = new WmlXsltExporterDelegate<FOSettings, FOConversionContext>("org/docx4j/convert/out/fo/docx2fo.xslt");
|
||||
|
||||
protected static FOExporterXslt instance = null;
|
||||
|
||||
protected FOExporterXslt() {
|
||||
super(EXPORTER_DELEGATE);
|
||||
}
|
||||
|
||||
public static Exporter<FOSettings> getInstance() {
|
||||
if (instance == null)
|
||||
synchronized (FOExporterXslt.class) {
|
||||
if (instance == null)
|
||||
instance = new FOExporterXslt();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
package org.docx4j.convert.out.fo;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import org.docx4j.Docx4J;
|
||||
import org.docx4j.TraversalUtil;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.convert.out.FOSettings;
|
||||
import org.docx4j.convert.out.common.ConversionSectionWrapper;
|
||||
import org.docx4j.convert.out.common.ConversionSectionWrappers;
|
||||
import org.docx4j.finders.SectPrFinder;
|
||||
import org.docx4j.jaxb.Context;
|
||||
import org.docx4j.model.structure.PageDimensions;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.docx4j.wml.HpsMeasure;
|
||||
import org.docx4j.wml.ObjectFactory;
|
||||
import org.docx4j.wml.P;
|
||||
import org.docx4j.wml.PPr;
|
||||
import org.docx4j.wml.PPrBase;
|
||||
import org.docx4j.wml.ParaRPr;
|
||||
import org.docx4j.wml.R;
|
||||
import org.docx4j.wml.RPr;
|
||||
import org.docx4j.wml.SectPr;
|
||||
import org.docx4j.wml.Text;
|
||||
import org.plutext.jaxb.xslfo.LayoutMasterSet;
|
||||
import org.plutext.jaxb.xslfo.SimplePageMaster;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
public class FOPAreaTreeHelper {
|
||||
protected static Logger log = LoggerFactory.getLogger(FOPAreaTreeHelper.class);
|
||||
|
||||
static void trimContent(WordprocessingMLPackage hfPkg) {
|
||||
SectPrFinder sf = new SectPrFinder(hfPkg.getMainDocumentPart());
|
||||
try {
|
||||
new TraversalUtil(hfPkg.getMainDocumentPart().getContents(), sf);
|
||||
} catch (Docx4JException e) {
|
||||
log.error(e.getMessage(), (Throwable)e);
|
||||
}
|
||||
List<SectPr> sectPrList = sf.getSectPrList();
|
||||
if (hfPkg.getMainDocumentPart().getJaxbElement().getBody().getSectPr() != null)
|
||||
sectPrList.remove(0);
|
||||
P filler = createFillerP();
|
||||
List<Object> contents = hfPkg.getMainDocumentPart().getContent();
|
||||
contents.clear();
|
||||
for (SectPr sectPr : sectPrList) {
|
||||
contents.add(filler);
|
||||
contents.add(filler);
|
||||
contents.add(filler);
|
||||
contents.add(filler);
|
||||
P p = Context.getWmlObjectFactory().createP();
|
||||
PPr ppr = Context.getWmlObjectFactory().createPPr();
|
||||
p.setPPr(ppr);
|
||||
ppr.setSectPr(sectPr);
|
||||
contents.add(p);
|
||||
}
|
||||
if (hfPkg.getMainDocumentPart().getJaxbElement().getBody().getSectPr() != null) {
|
||||
contents.add(filler);
|
||||
contents.add(filler);
|
||||
contents.add(filler);
|
||||
contents.add(filler);
|
||||
}
|
||||
}
|
||||
|
||||
private static P createFillerP() {
|
||||
ObjectFactory wmlObjectFactory = Context.getWmlObjectFactory();
|
||||
P p = wmlObjectFactory.createP();
|
||||
PPr ppr = wmlObjectFactory.createPPr();
|
||||
p.setPPr(ppr);
|
||||
ParaRPr pararpr = wmlObjectFactory.createParaRPr();
|
||||
PPrBase.Spacing pprbasespacing = wmlObjectFactory.createPPrBaseSpacing();
|
||||
ppr.setSpacing(pprbasespacing);
|
||||
pprbasespacing.setBefore(BigInteger.valueOf(800L));
|
||||
pprbasespacing.setAfter(BigInteger.valueOf(800L));
|
||||
R r = wmlObjectFactory.createR();
|
||||
p.getContent().add(r);
|
||||
RPr rpr = wmlObjectFactory.createRPr();
|
||||
r.setRPr(rpr);
|
||||
HpsMeasure hpsmeasure3 = wmlObjectFactory.createHpsMeasure();
|
||||
rpr.setSz(hpsmeasure3);
|
||||
hpsmeasure3.setVal(BigInteger.valueOf(96L));
|
||||
Text text = wmlObjectFactory.createText();
|
||||
JAXBElement<Text> textWrapped = wmlObjectFactory.createRT(text);
|
||||
r.getContent().add(textWrapped);
|
||||
text.setValue("BODY CONTENT");
|
||||
return p;
|
||||
}
|
||||
|
||||
static Document getAreaTreeViaFOP(WordprocessingMLPackage hfPkg, boolean useXSLT) throws Docx4JException, ParserConfigurationException, SAXException, IOException {
|
||||
FOSettings foSettings = Docx4J.createFOSettings();
|
||||
foSettings.setWmlPackage(hfPkg);
|
||||
foSettings.setApacheFopMime("application/X-fop-areatree");
|
||||
foSettings.setLayoutMasterSetCalculationInProgress(true);
|
||||
if (log.isDebugEnabled())
|
||||
foSettings.setFoDumpFile(new File(System.getProperty("user.dir") + "/hf.fo"));
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
if (useXSLT) {
|
||||
Docx4J.toFO(foSettings, os, 1);
|
||||
} else {
|
||||
Docx4J.toFO(foSettings, os, 2);
|
||||
}
|
||||
InputStream is = new ByteArrayInputStream(os.toByteArray());
|
||||
DocumentBuilder builder = XmlUtils.getNewDocumentBuilder();
|
||||
return builder.parse(is);
|
||||
}
|
||||
|
||||
static void calculateHFExtents(Document areaTree, Map<String, Integer> headerBpda, Map<String, Integer> footerBpda) {
|
||||
if (log.isDebugEnabled())
|
||||
log.debug(XmlUtils.w3CDomNodeToString(areaTree));
|
||||
for (int i = 0; i < areaTree.getDocumentElement().getChildNodes().getLength(); i++) {
|
||||
Node pageSequence = areaTree.getDocumentElement().getChildNodes().item(i);
|
||||
if (pageSequence instanceof Element)
|
||||
if (!pageSequence.getLocalName().equals("pageSequence")) {
|
||||
log.error("Unexpected element: " + pageSequence.getLocalName());
|
||||
} else {
|
||||
for (int j = 0; j < pageSequence.getChildNodes().getLength(); j++) {
|
||||
Node pageViewport = pageSequence.getChildNodes().item(j);
|
||||
if (pageViewport instanceof Element)
|
||||
if (!pageViewport.getLocalName().equals("pageViewport")) {
|
||||
log.error("Unexpected element: " + pageViewport.getLocalName());
|
||||
} else {
|
||||
String simplePageMasterName = ((Element)pageViewport).getAttribute("simple-page-master-name");
|
||||
log.debug("processing simple-page-master-name: " + simplePageMasterName);
|
||||
if (headerBpda.containsKey(simplePageMasterName)) {
|
||||
log.debug(".. dupe .. ignore");
|
||||
} else {
|
||||
Element page = (Element)pageViewport.getFirstChild();
|
||||
for (int k = 0; k < page.getChildNodes().getLength(); k++) {
|
||||
Node regionViewport = page.getChildNodes().item(k);
|
||||
if (regionViewport instanceof Element) {
|
||||
Element region = (Element)regionViewport.getFirstChild();
|
||||
int bpda = 0;
|
||||
if (region.getLocalName().equals("regionBefore") || region.getLocalName().equals("regionAfter"))
|
||||
for (int m = 0; m < region.getChildNodes().getLength(); m++) {
|
||||
Element block = (Element)region.getChildNodes().item(m);
|
||||
if (block.getLocalName().equals("block")) {
|
||||
try {
|
||||
bpda += Integer.parseInt(block.getAttribute("bpda"));
|
||||
} catch (NumberFormatException nfe) {
|
||||
log.error("For @bpda, \n" + XmlUtils.w3CDomNodeToString(block));
|
||||
log.error(nfe.getMessage(), (Throwable)nfe);
|
||||
}
|
||||
} else {
|
||||
log.debug(simplePageMasterName + " - Unexpected element: " + block.getLocalName());
|
||||
}
|
||||
}
|
||||
if (region.getLocalName().equals("regionBefore")) {
|
||||
headerBpda.put(simplePageMasterName, Integer.valueOf(bpda));
|
||||
} else if (region.getLocalName().equals("regionAfter")) {
|
||||
footerBpda.put(simplePageMasterName, Integer.valueOf(bpda));
|
||||
} else if (!region.getLocalName().equals("regionBody")) {
|
||||
log.error("unexpected region: " + region.getLocalName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void adjustLayoutMasterSet(LayoutMasterSet layoutMasterSet, ConversionSectionWrappers conversionSectionWrappers, Map<String, Integer> headerBpda, Map<String, Integer> footerBpda) {
|
||||
List<ConversionSectionWrapper> sections = conversionSectionWrappers.getList();
|
||||
ConversionSectionWrapper section = null;
|
||||
for (Object o : (Iterable<Object>)layoutMasterSet.getSimplePageMasterOrPageSequenceMaster()) {
|
||||
if (o instanceof SimplePageMaster) {
|
||||
SimplePageMaster spm = (SimplePageMaster)o;
|
||||
String simplePageMasterName = spm.getMasterName();
|
||||
int index = -1 + Integer.parseInt(simplePageMasterName.substring(1, simplePageMasterName.indexOf("-")));
|
||||
PageDimensions page = null;
|
||||
if (sections.get(index) == null) {
|
||||
log.error("Couldn't find section " + index + " from " + simplePageMasterName);
|
||||
} else {
|
||||
page = sections.get(index).getPageDimensions();
|
||||
}
|
||||
if (spm.getRegionBefore() != null) {
|
||||
Integer hBpdaMilliPts = headerBpda.get(simplePageMasterName);
|
||||
if (hBpdaMilliPts == null) {
|
||||
log.error("No headerBpda for " + simplePageMasterName);
|
||||
} else {
|
||||
float hBpdaPts = (float)(hBpdaMilliPts / 1000);
|
||||
spm.getRegionBefore().setExtent(hBpdaPts + "pt");
|
||||
spm.getRegionBody().setMarginTop(hBpdaPts + "pt");
|
||||
float totalHeight = (float)(page.getHeaderMargin() / 20) + hBpdaPts;
|
||||
float extraMargin = (float)(page.getPgMar().getTop().intValue() / 20) - totalHeight;
|
||||
if (extraMargin > 0.0F) {
|
||||
float required = (float)((page.getPgMar().getTop().intValue() - page.getHeaderMargin()) / 20);
|
||||
spm.getRegionBody().setMarginTop(required + "pt");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (spm.getRegionAfter() != null) {
|
||||
Integer fBpdaMilliPts = footerBpda.get(simplePageMasterName);
|
||||
if (fBpdaMilliPts == null) {
|
||||
log.error("No footerBpda for " + simplePageMasterName);
|
||||
continue;
|
||||
}
|
||||
float fBpdaPts = (float)(fBpdaMilliPts / 1000);
|
||||
spm.getRegionAfter().setExtent(fBpdaPts + "pt");
|
||||
spm.getRegionBody().setMarginBottom(fBpdaPts + "pt");
|
||||
float totalHeight = (float)(page.getFooterMargin() / 20) + fBpdaPts;
|
||||
float extraMargin = (float)(page.getPgMar().getBottom().intValue() / 20) - totalHeight;
|
||||
if (extraMargin > 0.0F) {
|
||||
float required = (float)((page.getPgMar().getBottom().intValue() - page.getFooterMargin()) / 20);
|
||||
spm.getRegionBody().setMarginBottom(required + "pt");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,445 @@
|
|||
package org.docx4j.convert.out.fo;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.convert.out.FORenderer;
|
||||
import org.docx4j.convert.out.FOSettings;
|
||||
import org.docx4j.convert.out.common.AbstractWmlConversionContext;
|
||||
import org.docx4j.convert.out.common.ConversionSectionWrapper;
|
||||
import org.docx4j.convert.out.common.Writer;
|
||||
import org.docx4j.convert.out.common.writer.AbstractPictWriter;
|
||||
import org.docx4j.convert.out.fo.renderers.AbstractFORenderer;
|
||||
import org.docx4j.model.structure.PageDimensions;
|
||||
import org.docx4j.vml.CTTextbox;
|
||||
import org.docx4j.vml.VmlAllCoreAttributes;
|
||||
import org.docx4j.vml.VmlShapeElements;
|
||||
import org.docx4j.vml.wordprocessingDrawing.CTWrap;
|
||||
import org.docx4j.vml.wordprocessingDrawing.STVerticalAnchor;
|
||||
import org.docx4j.vml.wordprocessingDrawing.STWrapType;
|
||||
import org.docx4j.wml.Pict;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
public abstract class FOPictWriterAbstract extends AbstractPictWriter {
|
||||
protected static Logger log = LoggerFactory.getLogger(FOPictWriterAbstract.class);
|
||||
|
||||
private static String XSL_FO = "http://www.w3.org/1999/XSL/Format";
|
||||
|
||||
public abstract boolean foRendererSupportsFoFloat();
|
||||
|
||||
public Node toNode(AbstractWmlConversionContext context, Object unmarshalledNode, Node modelContent, Writer.TransformState state, Document doc) throws TransformerException {
|
||||
Pict pict = (Pict)unmarshalledNode;
|
||||
VmlShapeElements shape = null;
|
||||
for (Object o : pict.getAnyAndAny()) {
|
||||
o = XmlUtils.unwrap(o);
|
||||
if (o instanceof VmlShapeElements && !(o instanceof org.docx4j.vml.CTShapetype)) {
|
||||
shape = (VmlShapeElements)o;
|
||||
log.debug("Found " + shape.getClass().getName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (shape == null)
|
||||
return context.getMessageWriter().message(context, "Couldn't find v:shape (or v:rectangle etc) in w:pict.");
|
||||
CTTextbox textBox = null;
|
||||
CTWrap w10Wrap = null;
|
||||
for (JAXBElement<?> o : shape.getEGShapeElements()) {
|
||||
o = (JAXBElement<?>)XmlUtils.unwrap(o);
|
||||
if (o instanceof CTTextbox)
|
||||
textBox = (CTTextbox)o;
|
||||
if (o instanceof CTWrap)
|
||||
w10Wrap = (CTWrap)o;
|
||||
}
|
||||
if (textBox == null)
|
||||
return context.getMessageWriter().message(context, "Couldn't find v:textbox in w:shape.");
|
||||
Map<String, String> props = null;
|
||||
if (shape instanceof VmlAllCoreAttributes) {
|
||||
props = getProperties(((VmlAllCoreAttributes)shape).getStyle());
|
||||
} else {
|
||||
log.warn(shape.getClass().getName() + " does not implement VmlAllCoreAttributes, so can't access @style if present");
|
||||
return context.getMessageWriter().message(context, shape.getClass().getName() + " does not implement VmlAllCoreAttributes, so can't access @style if present");
|
||||
}
|
||||
boolean wrap = true;
|
||||
if (w10Wrap != null) {
|
||||
if (w10Wrap.getType() != null && (w10Wrap.getType().equals(STWrapType.TOP_AND_BOTTOM) || w10Wrap.getType().equals(STWrapType.SQUARE) || w10Wrap.getType().equals(STWrapType.TIGHT) || w10Wrap.getType().equals(STWrapType.THROUGH)))
|
||||
wrap = false;
|
||||
if (w10Wrap.getAnchory() != null && w10Wrap.getAnchory().equals(STVerticalAnchor.PAGE))
|
||||
wrap = false;
|
||||
}
|
||||
return handleVTextBox(context, modelContent, doc, shape, props, wrap);
|
||||
}
|
||||
|
||||
public Node handleVTextBox(AbstractWmlConversionContext context, Node modelContent, Document doc, VmlShapeElements shape, Map<String, String> props, boolean wrap) {
|
||||
String mso_position_vertical_relative = props.get("mso-position-vertical-relative");
|
||||
String mso_position_vertical = props.get("mso-position-vertical");
|
||||
ConversionSectionWrapper csw = context.getSections().getCurrentSection();
|
||||
PageDimensions pageDimensions = csw.getPageDimensions();
|
||||
int writableWidthTwips = pageDimensions.getWritableWidthTwips();
|
||||
float writableWidthPts = (float)(writableWidthTwips / 20);
|
||||
int writableHeightTwips = pageDimensions.getWritableHeightTwips();
|
||||
float writableHeightPts = (float)(writableHeightTwips / 20);
|
||||
FORenderer foRenderer = ((FOSettings)context.getConversionSettings()).getCustomFoRenderer();
|
||||
log.debug(foRenderer.getClass().getName());
|
||||
if (wrap) {
|
||||
log.debug("textbox - wrapped text");
|
||||
if (mso_position_vertical_relative == null) {
|
||||
try {
|
||||
log.warn(XmlUtils.marshaltoString(shape));
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage());
|
||||
}
|
||||
return context.getMessageWriter().message(context, "mso_position_vertical_relative==null. What to do?");
|
||||
}
|
||||
if (mso_position_vertical_relative.equals("text")) {
|
||||
Element element = doc.createElementNS(XSL_FO, "block");
|
||||
setBorders(element);
|
||||
String str = props.get("margin-top");
|
||||
if (str == null) {
|
||||
log.error("margin top prop not found. What to do?");
|
||||
XmlUtils.treeCopy(modelContent.getChildNodes(), element);
|
||||
return element;
|
||||
}
|
||||
float marginTop = parsePtsVal(str);
|
||||
if (foRendererSupportsFoFloat()) {
|
||||
String str1 = props.get("mso-position-horizontal-relative");
|
||||
String str2 = props.get("mso-position-horizontal");
|
||||
if (str1 == null) {
|
||||
log.warn("No support for mso_position_horizontal_relative==null");
|
||||
XmlUtils.treeCopy(modelContent.getChildNodes(), element);
|
||||
return element;
|
||||
}
|
||||
if (!str1.equals("text")) {
|
||||
log.warn("No support for mso_position_horizontal_relative==" + str1.equals("text"));
|
||||
XmlUtils.treeCopy(modelContent.getChildNodes(), element);
|
||||
return element;
|
||||
}
|
||||
float ml = parsePtsVal(props.get("margin-left"));
|
||||
if (str2 == null) {
|
||||
log.warn("No support for mso_position_horizontal==null");
|
||||
XmlUtils.treeCopy(modelContent.getChildNodes(), element);
|
||||
return element;
|
||||
}
|
||||
if (str2.equals("absolute")) {
|
||||
log.warn("Degrading absolute position to left/right");
|
||||
if ((double)(ml / writableWidthPts) <= 0.5D) {
|
||||
str2 = "left";
|
||||
} else {
|
||||
str2 = "right";
|
||||
}
|
||||
}
|
||||
element = doc.createElementNS(XSL_FO, "float");
|
||||
setBorders(element);
|
||||
if (str2.equals("left")) {
|
||||
element.setAttribute("float", "start");
|
||||
} else if (str2.equals("center")) {
|
||||
log.warn("Degrading center to right");
|
||||
element.setAttribute("float", "end");
|
||||
} else if (str2.equals("right")) {
|
||||
element.setAttribute("float", "end");
|
||||
}
|
||||
XmlUtils.treeCopy(modelContent.getChildNodes(), element);
|
||||
} else if (marginTop <= 0.0F) {
|
||||
marginTopZeroCase(props, element, writableWidthPts);
|
||||
XmlUtils.treeCopy(modelContent.getChildNodes(), element);
|
||||
} else {
|
||||
element = doc.createElementNS(XSL_FO, "table");
|
||||
if (!marginTopPositiveCase(foRenderer, props, doc, element, writableWidthPts, modelContent.getChildNodes())) {
|
||||
element = doc.createElementNS(XSL_FO, "block");
|
||||
setBorders(element);
|
||||
XmlUtils.treeCopy(modelContent.getChildNodes(), element);
|
||||
}
|
||||
}
|
||||
log.debug(XmlUtils.w3CDomNodeToString(element));
|
||||
return element;
|
||||
}
|
||||
if (foRendererSupportsFoFloat()) {
|
||||
if (mso_position_vertical_relative.equals("page") || mso_position_vertical_relative.equals("top-margin-area") || mso_position_vertical_relative.equals("bottom-margin-area")) {
|
||||
if (mso_position_vertical_relative.equals("page")) {
|
||||
if (mso_position_vertical.equals("top")) {
|
||||
Element element = doc.createElementNS(XSL_FO, "float");
|
||||
element.setAttribute("float", "before");
|
||||
setBorders(element);
|
||||
log.debug(XmlUtils.w3CDomNodeToString(element));
|
||||
return element;
|
||||
}
|
||||
if (mso_position_vertical.equals("bottom")) {
|
||||
Element element1 = doc.createElementNS(XSL_FO, "footnote");
|
||||
Element footnoteBody = doc.createElementNS(XSL_FO, "footnote-body");
|
||||
element1.appendChild(footnoteBody);
|
||||
Element block = doc.createElementNS(XSL_FO, "block");
|
||||
footnoteBody.appendChild(block);
|
||||
setBorders(block);
|
||||
XmlUtils.treeCopy(modelContent.getChildNodes(), block);
|
||||
return element1;
|
||||
}
|
||||
log.warn("No support for mso_position_vertical==" + mso_position_vertical);
|
||||
return context.getMessageWriter().message(context, "TODO for fo:float capable renderer, support no-wrap + mso-position-vertical=" + mso_position_vertical);
|
||||
}
|
||||
if (mso_position_vertical_relative.equals("top-margin-area")) {
|
||||
Element element = doc.createElementNS(XSL_FO, "float");
|
||||
element.setAttribute("float", "before");
|
||||
setBorders(element);
|
||||
log.debug(XmlUtils.w3CDomNodeToString(element));
|
||||
return element;
|
||||
}
|
||||
if (mso_position_vertical_relative.equals("bottom-margin-area")) {
|
||||
Element element1 = doc.createElementNS(XSL_FO, "footnote");
|
||||
Element footnoteBody = doc.createElementNS(XSL_FO, "footnote-body");
|
||||
element1.appendChild(footnoteBody);
|
||||
Element block = doc.createElementNS(XSL_FO, "block");
|
||||
footnoteBody.appendChild(block);
|
||||
setBorders(block);
|
||||
XmlUtils.treeCopy(modelContent.getChildNodes(), block);
|
||||
return element1;
|
||||
}
|
||||
return context.getMessageWriter().message(context, "TODO (how did we get here?) mso-position-vertical-relative=" + mso_position_vertical_relative);
|
||||
}
|
||||
return context.getMessageWriter().message(context, "TODO for fo:float capable renderer, support no-wrap + mso-position-vertical-relative=" + mso_position_vertical_relative);
|
||||
}
|
||||
return context.getMessageWriter().message(context, "TODO for fo:float INcapable renderer, support no-wrap + mso-position-vertical-relative=" + mso_position_vertical_relative);
|
||||
}
|
||||
log.debug("textbox - over/behind docx text");
|
||||
Element ret = doc.createElementNS(XSL_FO, "block-container");
|
||||
XmlUtils.treeCopy(modelContent.getChildNodes(), ret);
|
||||
setBorders(ret);
|
||||
String mso_position_horizontal_relative = props.get("mso-position-horizontal-relative");
|
||||
String mso_position_horizontal = props.get("mso-position-horizontal");
|
||||
if (mso_position_horizontal_relative == null) {
|
||||
log.warn("No support for mso_position_horizontal_relative==null");
|
||||
} else if (!mso_position_horizontal_relative.equals("text")) {
|
||||
log.warn("No support for mso_position_horizontal_relative==" + mso_position_horizontal_relative.equals("text"));
|
||||
} else {
|
||||
float boxWidth = parsePtsVal(props.get("width"));
|
||||
ret.setAttribute("width", props.get("width"));
|
||||
ret.setAttribute("height", props.get("height"));
|
||||
if (mso_position_horizontal == null) {
|
||||
log.warn("No support for mso_position_horizontal==null");
|
||||
} else if (mso_position_horizontal.equals("left")) {
|
||||
ret.setAttribute("left", "0pt");
|
||||
} else if (mso_position_horizontal.equals("center")) {
|
||||
int marginLeft = Math.round((writableWidthPts - boxWidth) / 2.0F);
|
||||
ret.setAttribute("left", marginLeft + "pt");
|
||||
} else if (mso_position_horizontal.equals("right")) {
|
||||
int marginLeft = Math.round(writableWidthPts - boxWidth);
|
||||
ret.setAttribute("left", marginLeft + "pt");
|
||||
} else if (mso_position_horizontal.equals("absolute")) {
|
||||
ret.setAttribute("margin-left", props.get("margin-left"));
|
||||
}
|
||||
}
|
||||
ret.setAttribute("z-index", props.get("z-index"));
|
||||
String margin_top = props.get("margin-top");
|
||||
if (mso_position_vertical_relative == null) {
|
||||
log.warn(XmlUtils.marshaltoString(shape));
|
||||
return context.getMessageWriter().message(context, "mso_position_vertical_relative==null. What to do?");
|
||||
}
|
||||
if (mso_position_vertical_relative.equals("text")) {
|
||||
ret.setAttribute("position", "absolute");
|
||||
if (margin_top != null)
|
||||
ret.setAttribute("top", margin_top);
|
||||
log.debug(XmlUtils.w3CDomNodeToString(ret));
|
||||
return ret;
|
||||
}
|
||||
if (mso_position_vertical_relative.equals("page") || mso_position_vertical_relative.equals("top-margin-area") || mso_position_vertical_relative.equals("bottom-margin-area")) {
|
||||
ret.setAttribute("position", "fixed");
|
||||
if (mso_position_vertical_relative.equals("page")) {
|
||||
if (mso_position_vertical.equals("top")) {
|
||||
if (margin_top != null)
|
||||
ret.setAttribute("top", margin_top);
|
||||
} else if (mso_position_vertical.equals("bottom")) {
|
||||
int top = Math.round(writableHeightPts);
|
||||
ret.setAttribute("top", top + "pt");
|
||||
} else {
|
||||
log.warn("No support for mso_position_vertical==" + mso_position_vertical);
|
||||
}
|
||||
log.debug(XmlUtils.w3CDomNodeToString(ret));
|
||||
return ret;
|
||||
}
|
||||
if (mso_position_vertical_relative.equals("top-margin-area")) {
|
||||
if (margin_top != null)
|
||||
ret.setAttribute("top", margin_top);
|
||||
log.debug(XmlUtils.w3CDomNodeToString(ret));
|
||||
return ret;
|
||||
}
|
||||
if (mso_position_vertical_relative.equals("bottom-margin-area")) {
|
||||
int top = Math.round(writableHeightPts);
|
||||
ret.setAttribute("top", top + "pt");
|
||||
log.debug(XmlUtils.w3CDomNodeToString(ret));
|
||||
return ret;
|
||||
}
|
||||
return context.getMessageWriter().message(context, "TODO (how did we get here?) mso-position-vertical-relative=" + mso_position_vertical_relative);
|
||||
}
|
||||
return context.getMessageWriter().message(context, "TODO support no-wrap + mso-position-vertical-relative=" + mso_position_vertical_relative);
|
||||
}
|
||||
|
||||
private void setBorders(Element ret) {
|
||||
ret.setAttribute("border-left-style", "solid");
|
||||
ret.setAttribute("border-top-style", "solid");
|
||||
ret.setAttribute("border-bottom-style", "solid");
|
||||
ret.setAttribute("border-right-style", "solid");
|
||||
}
|
||||
|
||||
private Map<String, String> getProperties(String s) {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
if (s == null) {
|
||||
log.warn("shape has no @style");
|
||||
return map;
|
||||
}
|
||||
for (String entry : s.split(";")) {
|
||||
String[] parts = entry.split(":");
|
||||
assert parts.length == 2 : "Invalid entry: " + entry;
|
||||
map.put(parts[0], parts[1]);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private float parsePtsVal(String pts) {
|
||||
if (pts == null) {
|
||||
log.warn("No val!");
|
||||
return -99.0F;
|
||||
}
|
||||
if (pts.contains("pt")) {
|
||||
pts = pts.substring(0, pts.indexOf("pt"));
|
||||
return Float.parseFloat(pts);
|
||||
}
|
||||
if (pts.equals("0"))
|
||||
return 0.0F;
|
||||
log.warn("Unit is not points! " + pts);
|
||||
return -99.0F;
|
||||
}
|
||||
|
||||
private void marginTopZeroCase(Map<String, String> props, Element ret, float widthPts) {
|
||||
String mso_position_horizontal_relative = props.get("mso-position-horizontal-relative");
|
||||
String mso_position_horizontal = props.get("mso-position-horizontal");
|
||||
if (mso_position_horizontal_relative == null) {
|
||||
log.warn("No support for mso_position_horizontal_relative==null");
|
||||
} else if (!mso_position_horizontal_relative.equals("text")) {
|
||||
log.warn("No support for mso_position_horizontal_relative==" + mso_position_horizontal_relative.equals("text"));
|
||||
} else {
|
||||
float boxWidth = parsePtsVal(props.get("width"));
|
||||
if (mso_position_horizontal == null) {
|
||||
log.warn("No support for mso_position_horizontal==null");
|
||||
} else if (mso_position_horizontal.equals("left")) {
|
||||
ret.setAttribute("margin-left", "0pt");
|
||||
int marginRight = Math.round(widthPts - boxWidth);
|
||||
ret.setAttribute("margin-right", marginRight + "pt");
|
||||
} else if (mso_position_horizontal.equals("center")) {
|
||||
int marginLeft = Math.round((widthPts - boxWidth) / 2.0F);
|
||||
ret.setAttribute("margin-left", marginLeft + "pt");
|
||||
ret.setAttribute("margin-right", marginLeft + "pt");
|
||||
} else if (mso_position_horizontal.equals("right")) {
|
||||
ret.setAttribute("margin-right", "0pt");
|
||||
int marginLeft = Math.round(widthPts - boxWidth);
|
||||
ret.setAttribute("margin-left", marginLeft + "pt");
|
||||
} else if (mso_position_horizontal.equals("absolute")) {
|
||||
ret.setAttribute("margin-left", props.get("margin-left"));
|
||||
float ml = parsePtsVal(props.get("margin-left"));
|
||||
int mRight = Math.round(widthPts - (boxWidth + ml));
|
||||
ret.setAttribute("margin-right", mRight + "pt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean marginTopPositiveCase(FORenderer foRenderer, Map<String, String> props, Document doc, Element ret, float widthPts, NodeList childNodes) {
|
||||
String mso_position_horizontal_relative = props.get("mso-position-horizontal-relative");
|
||||
String mso_position_horizontal = props.get("mso-position-horizontal");
|
||||
if (mso_position_horizontal_relative == null) {
|
||||
log.warn("No support for mso_position_horizontal_relative==null");
|
||||
return false;
|
||||
}
|
||||
if (!mso_position_horizontal_relative.equals("text")) {
|
||||
log.warn("No support for mso_position_horizontal_relative==" + mso_position_horizontal_relative.equals("text"));
|
||||
return false;
|
||||
}
|
||||
float boxWidth = parsePtsVal(props.get("width"));
|
||||
if (mso_position_horizontal == null) {
|
||||
log.warn("No support for mso_position_horizontal==null");
|
||||
return false;
|
||||
}
|
||||
float ml = parsePtsVal(props.get("margin-left"));
|
||||
if (mso_position_horizontal.equals("absolute"))
|
||||
if ((double)(ml / widthPts) < 0.334D) {
|
||||
mso_position_horizontal = "left";
|
||||
} else if ((double)(ml / widthPts) < 0.665D) {
|
||||
mso_position_horizontal = "right";
|
||||
} else {
|
||||
mso_position_horizontal = "center";
|
||||
}
|
||||
if (mso_position_horizontal.equals("left")) {
|
||||
Element tcol1 = doc.createElementNS(XSL_FO, "table-column");
|
||||
ret.appendChild(tcol1);
|
||||
tcol1.setAttribute("column-number", "1");
|
||||
int col1W = Math.round(ml + boxWidth);
|
||||
tcol1.setAttribute("column-width", col1W + "pt");
|
||||
Element tcol2 = doc.createElementNS(XSL_FO, "table-column");
|
||||
ret.appendChild(tcol2);
|
||||
tcol2.setAttribute("column-number", "2");
|
||||
int col2W = Math.round(widthPts - (float)col1W);
|
||||
tcol2.setAttribute("column-width", col2W + "pt");
|
||||
Element tbody = doc.createElementNS(XSL_FO, "table-body");
|
||||
ret.appendChild(tbody);
|
||||
Element trow = doc.createElementNS(XSL_FO, "table-row");
|
||||
tbody.appendChild(trow);
|
||||
Element tc1 = doc.createElementNS(XSL_FO, "table-cell");
|
||||
trow.appendChild(tc1);
|
||||
Element block = doc.createElementNS(XSL_FO, "block");
|
||||
setBorders(block);
|
||||
tc1.appendChild(block);
|
||||
XmlUtils.treeCopy(childNodes, block);
|
||||
Element tc2 = doc.createElementNS(XSL_FO, "table-cell");
|
||||
trow.appendChild(tc2);
|
||||
Element placeholder = doc.createElementNS(XSL_FO, "block");
|
||||
placeholder.setTextContent("#TEXTBOX#");
|
||||
tc2.appendChild(placeholder);
|
||||
if (foRenderer instanceof AbstractFORenderer) {
|
||||
((AbstractFORenderer)foRenderer).TEXTBOX_POSTPROCESSING_REQUIRED = true;
|
||||
} else {
|
||||
log.warn("TODO: implement TEXTBOX_POSTPROCESSING_REQUIRED for " + foRenderer.getClass().getName());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (mso_position_horizontal.equals("center")) {
|
||||
log.warn("Can't support mso_position_horizontal:center");
|
||||
return false;
|
||||
}
|
||||
if (mso_position_horizontal.equals("right")) {
|
||||
Element tcol1 = doc.createElementNS(XSL_FO, "table-column");
|
||||
ret.appendChild(tcol1);
|
||||
tcol1.setAttribute("column-number", "1");
|
||||
int col1W = Math.round(widthPts - boxWidth);
|
||||
tcol1.setAttribute("column-width", col1W + "pt");
|
||||
Element tcol2 = doc.createElementNS(XSL_FO, "table-column");
|
||||
ret.appendChild(tcol2);
|
||||
tcol2.setAttribute("column-number", "2");
|
||||
int col2W = Math.round(boxWidth);
|
||||
tcol2.setAttribute("column-width", col2W + "pt");
|
||||
Element tbody = doc.createElementNS(XSL_FO, "table-body");
|
||||
ret.appendChild(tbody);
|
||||
Element trow = doc.createElementNS(XSL_FO, "table-row");
|
||||
tbody.appendChild(trow);
|
||||
Element tc1 = doc.createElementNS(XSL_FO, "table-cell");
|
||||
trow.appendChild(tc1);
|
||||
Element placeholder = doc.createElementNS(XSL_FO, "block");
|
||||
placeholder.setTextContent("#TEXTBOX#");
|
||||
tc1.appendChild(placeholder);
|
||||
Element tc2 = doc.createElementNS(XSL_FO, "table-cell");
|
||||
trow.appendChild(tc2);
|
||||
Element block = doc.createElementNS(XSL_FO, "block");
|
||||
setBorders(block);
|
||||
tc2.appendChild(block);
|
||||
XmlUtils.treeCopy(childNodes, block);
|
||||
if (foRenderer instanceof AbstractFORenderer) {
|
||||
((AbstractFORenderer)foRenderer).TEXTBOX_POSTPROCESSING_REQUIRED = true;
|
||||
} else {
|
||||
log.warn("TODO: implement TEXTBOX_POSTPROCESSING_REQUIRED for " + foRenderer.getClass().getName());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package org.docx4j.convert.out.fo;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class FOPictWriterFloatAvoided extends FOPictWriterAbstract {
|
||||
protected static Logger log = LoggerFactory.getLogger(FOPictWriterFloatAvoided.class);
|
||||
|
||||
public boolean foRendererSupportsFoFloat() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package org.docx4j.convert.out.fo;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class FOPictWriterFloatUsed extends FOPictWriterAbstract {
|
||||
protected static Logger log = LoggerFactory.getLogger(FOPictWriterFloatUsed.class);
|
||||
|
||||
public boolean foRendererSupportsFoFloat() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
package org.docx4j.convert.out.fo;
|
||||
|
||||
import java.util.List;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.docx4j.convert.out.common.AbstractWmlConversionContext;
|
||||
import org.docx4j.convert.out.common.ConversionSectionWrapper;
|
||||
import org.docx4j.convert.out.common.writer.AbstractFldSimpleWriter;
|
||||
import org.docx4j.convert.out.common.writer.AbstractPagerefHandler;
|
||||
import org.docx4j.convert.out.common.writer.RefHandler;
|
||||
import org.docx4j.model.fields.FldSimpleModel;
|
||||
import org.docx4j.model.properties.Property;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
public class FldSimpleWriter extends AbstractFldSimpleWriter {
|
||||
protected static final String FO_NS = "http://www.w3.org/1999/XSL/Format";
|
||||
|
||||
protected static final String XSL_NS = "http://www.w3.org/1999/XSL/Transform";
|
||||
|
||||
protected static class PageHandler implements AbstractFldSimpleWriter.FldSimpleNodeWriterHandler {
|
||||
public String getName() {
|
||||
return "PAGE";
|
||||
}
|
||||
|
||||
public int getProcessType() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public Node toNode(AbstractWmlConversionContext context, FldSimpleModel model, Document doc) throws TransformerException {
|
||||
return doc.createElementNS("http://www.w3.org/1999/XSL/Format", "fo:page-number");
|
||||
}
|
||||
}
|
||||
|
||||
protected static abstract class AbstractPagesHandler implements AbstractFldSimpleWriter.FldSimpleNodeWriterHandler {
|
||||
protected String fieldName = null;
|
||||
|
||||
protected AbstractPagesHandler(String fieldName) {
|
||||
this.fieldName = fieldName;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.fieldName;
|
||||
}
|
||||
|
||||
public int getProcessType() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public Node toNode(AbstractWmlConversionContext context, FldSimpleModel model, Document doc) throws TransformerException {
|
||||
Element ret = null;
|
||||
if (((FOConversionContext)context).isRequires2Pass()) {
|
||||
ret = doc.createElementNS("http://www.w3.org/1999/XSL/Format", "fo:inline");
|
||||
ret.appendChild(doc.createTextNode("${" + getParameterName(context) + "}"));
|
||||
} else {
|
||||
ret = doc.createElementNS("http://www.w3.org/1999/XSL/Format", "fo:wrapper");
|
||||
Element pncl = doc.createElementNS("http://www.w3.org/1999/XSL/Format", "fo:page-number-citation-last");
|
||||
String refId = getRefid(context);
|
||||
pncl.setAttribute("ref-id", getRefid(context));
|
||||
ret.appendChild(pncl);
|
||||
ret.appendChild(doc.createTextNode(""));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected abstract String getRefid(AbstractWmlConversionContext param1AbstractWmlConversionContext);
|
||||
|
||||
protected abstract String getParameterName(AbstractWmlConversionContext param1AbstractWmlConversionContext);
|
||||
}
|
||||
|
||||
protected static class NumpagesHandler extends AbstractPagesHandler {
|
||||
protected NumpagesHandler() {
|
||||
super("NUMPAGES");
|
||||
}
|
||||
|
||||
protected String getParameterName(AbstractWmlConversionContext context) {
|
||||
return "field_numpages_" + context.getSections().getCurrentSection().getId() + "_value";
|
||||
}
|
||||
|
||||
protected String getRefid(AbstractWmlConversionContext context) {
|
||||
List<ConversionSectionWrapper> wrappers = context.getSections().getList();
|
||||
return "section_" + wrappers.get(wrappers.size() - 1).getId();
|
||||
}
|
||||
}
|
||||
|
||||
protected static class SectionpagesHandler extends AbstractPagesHandler {
|
||||
protected SectionpagesHandler() {
|
||||
super("SECTIONPAGES");
|
||||
}
|
||||
|
||||
protected String getParameterName(AbstractWmlConversionContext context) {
|
||||
return "field_sectionpages_" + context.getSections().getCurrentSection().getId() + "_value";
|
||||
}
|
||||
|
||||
protected String getRefid(AbstractWmlConversionContext context) {
|
||||
return "section_" + context.getSections().getCurrentSection().getId();
|
||||
}
|
||||
}
|
||||
|
||||
protected static class PagerefHandler extends AbstractPagerefHandler {
|
||||
protected PagerefHandler() {
|
||||
super(2);
|
||||
}
|
||||
|
||||
protected Node createPageref(AbstractWmlConversionContext context, Document doc, String bookmarkId) {
|
||||
Element ret = doc.createElementNS("http://www.w3.org/1999/XSL/Format", "fo:page-number-citation");
|
||||
ret.setAttribute("ref-id", bookmarkId);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
protected FldSimpleWriter() {
|
||||
super("http://www.w3.org/1999/XSL/Format", "fo:inline");
|
||||
}
|
||||
|
||||
protected void registerHandlers() {
|
||||
super.registerHandlers();
|
||||
registerHandler(new PageHandler());
|
||||
registerHandler(new HyperlinkWriter());
|
||||
registerHandler(new RefHandler(2));
|
||||
registerHandler(new PagerefHandler());
|
||||
registerHandler(new NumpagesHandler());
|
||||
registerHandler(new SectionpagesHandler());
|
||||
}
|
||||
|
||||
protected void applyProperties(List<Property> properties, Node node) {
|
||||
XsltFOFunctions.applyFoAttributes(properties, (Element)node);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package org.docx4j.convert.out.fo;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.docx4j.convert.out.common.AbstractWmlConversionContext;
|
||||
import org.docx4j.convert.out.common.writer.AbstractHyperlinkWriter;
|
||||
import org.docx4j.convert.out.common.writer.AbstractHyperlinkWriterModel;
|
||||
import org.docx4j.convert.out.common.writer.HyperlinkUtil;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
public class HyperlinkWriter extends AbstractHyperlinkWriter {
|
||||
protected Node toNode(AbstractWmlConversionContext context, AbstractHyperlinkWriterModel model, Document doc) throws TransformerException {
|
||||
return HyperlinkUtil.toNode(2, context, model, model.getContent(), doc);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
package org.docx4j.convert.out.fo;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import org.docx4j.UnitsOfMeasurement;
|
||||
import org.docx4j.XmlUtils;
|
||||
import org.docx4j.convert.out.FOSettings;
|
||||
import org.docx4j.convert.out.common.AbstractWmlConversionContext;
|
||||
import org.docx4j.convert.out.common.ConversionSectionWrapper;
|
||||
import org.docx4j.convert.out.common.preprocess.PartialDeepCopy;
|
||||
import org.docx4j.events.EventFinished;
|
||||
import org.docx4j.events.StartEvent;
|
||||
import org.docx4j.events.WellKnownProcessSteps;
|
||||
import org.docx4j.jaxb.Context;
|
||||
import org.docx4j.model.structure.HeaderFooterPolicy;
|
||||
import org.docx4j.model.structure.PageDimensions;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.plutext.jaxb.xslfo.ConditionalPageMasterReference;
|
||||
import org.plutext.jaxb.xslfo.LayoutMasterSet;
|
||||
import org.plutext.jaxb.xslfo.ObjectFactory;
|
||||
import org.plutext.jaxb.xslfo.OddOrEvenType;
|
||||
import org.plutext.jaxb.xslfo.PagePositionType;
|
||||
import org.plutext.jaxb.xslfo.PageSequenceMaster;
|
||||
import org.plutext.jaxb.xslfo.RegionAfter;
|
||||
import org.plutext.jaxb.xslfo.RegionBefore;
|
||||
import org.plutext.jaxb.xslfo.RegionBody;
|
||||
import org.plutext.jaxb.xslfo.RepeatablePageMasterAlternatives;
|
||||
import org.plutext.jaxb.xslfo.SimplePageMaster;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
public class LayoutMasterSetBuilder {
|
||||
protected static Logger log = LoggerFactory.getLogger(LayoutMasterSetBuilder.class);
|
||||
|
||||
private static ObjectFactory factory;
|
||||
|
||||
public static DocumentFragment getLayoutMasterSetFragment(AbstractWmlConversionContext context) {
|
||||
LayoutMasterSet lms = getFoLayoutMasterSet(context);
|
||||
FOSettings foSettings = (FOSettings)context.getConversionSettings();
|
||||
if (!foSettings.lsLayoutMasterSetCalculationInProgress())
|
||||
fixExtents(lms, context, true);
|
||||
Document document = XmlUtils.marshaltoW3CDomDocument(lms, Context.getXslFoContext());
|
||||
DocumentFragment docfrag = document.createDocumentFragment();
|
||||
docfrag.appendChild(document.getDocumentElement());
|
||||
return docfrag;
|
||||
}
|
||||
|
||||
private static void fixExtents(LayoutMasterSet lms, AbstractWmlConversionContext context, boolean useXSLT) {
|
||||
WordprocessingMLPackage wordMLPackage = context.getWmlPackage();
|
||||
StartEvent startEvent = new StartEvent(wordMLPackage, WellKnownProcessSteps.FO_EXTENTS);
|
||||
startEvent.publish();
|
||||
log.debug("incoming LMS: " + XmlUtils.marshaltoString(lms, Context.getXslFoContext()));
|
||||
Set<String> relationshipTypes = new TreeSet<String>();
|
||||
relationshipTypes.add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument");
|
||||
relationshipTypes.add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/header");
|
||||
relationshipTypes.add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer");
|
||||
relationshipTypes.add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes");
|
||||
relationshipTypes.add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes");
|
||||
relationshipTypes.add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments");
|
||||
try {
|
||||
WordprocessingMLPackage hfPkg = (WordprocessingMLPackage)PartialDeepCopy.process(wordMLPackage, relationshipTypes);
|
||||
FOPAreaTreeHelper.trimContent(hfPkg);
|
||||
Document areaTree = FOPAreaTreeHelper.getAreaTreeViaFOP(hfPkg, useXSLT);
|
||||
log.debug(XmlUtils.w3CDomNodeToString(areaTree));
|
||||
Map<String, Integer> headerBpda = new HashMap<String, Integer>();
|
||||
Map<String, Integer> footerBpda = new HashMap<String, Integer>();
|
||||
FOPAreaTreeHelper.calculateHFExtents(areaTree, headerBpda, footerBpda);
|
||||
FOPAreaTreeHelper.adjustLayoutMasterSet(lms, context.getSections(), headerBpda, footerBpda);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
log.debug("resulting LMS: " + XmlUtils.marshaltoString(lms, Context.getXslFoContext()));
|
||||
new EventFinished(startEvent).publish();
|
||||
}
|
||||
|
||||
public static void appendLayoutMasterSetFragment(AbstractWmlConversionContext context, Node foRoot) {
|
||||
LayoutMasterSet lms = getFoLayoutMasterSet(context);
|
||||
FOSettings foSettings = (FOSettings)context.getConversionSettings();
|
||||
if (!foSettings.lsLayoutMasterSetCalculationInProgress())
|
||||
fixExtents(lms, context, false);
|
||||
Document document = XmlUtils.marshaltoW3CDomDocument(lms, Context.getXslFoContext());
|
||||
XmlUtils.treeCopy(document.getDocumentElement(), foRoot);
|
||||
}
|
||||
|
||||
private static LayoutMasterSet getFoLayoutMasterSet(AbstractWmlConversionContext context) {
|
||||
LayoutMasterSet lms = getFactory().createLayoutMasterSet();
|
||||
List<ConversionSectionWrapper> sections = context.getSections().getList();
|
||||
ConversionSectionWrapper section = null;
|
||||
for (int i = 0; i < sections.size(); i++) {
|
||||
section = sections.get(i);
|
||||
HeaderFooterPolicy hf = section.getHeaderFooterPolicy();
|
||||
String sectionName = "s" + Integer.toString(i + 1);
|
||||
if (hf.getFirstHeader() != null || hf.getFirstFooter() != null)
|
||||
lms.getSimplePageMasterOrPageSequenceMaster().add(createSimplePageMaster(sectionName + "-firstpage", section.getPageDimensions(), "firstpage", (hf.getFirstHeader() != null), (hf.getFirstFooter() != null)));
|
||||
if (hf.getEvenHeader() != null || hf.getEvenFooter() != null)
|
||||
lms.getSimplePageMasterOrPageSequenceMaster().add(createSimplePageMaster(sectionName + "-evenpage", section.getPageDimensions(), "evenpage", (hf.getEvenHeader() != null), (hf.getEvenFooter() != null)));
|
||||
if (hf.getDefaultHeader() != null || hf.getDefaultFooter() != null)
|
||||
lms.getSimplePageMasterOrPageSequenceMaster().add(createSimplePageMaster(sectionName + "-default", section.getPageDimensions(), "default", (hf.getDefaultHeader() != null), (hf.getDefaultFooter() != null)));
|
||||
if (hf.getDefaultHeader() == null && hf.getDefaultFooter() == null)
|
||||
lms.getSimplePageMasterOrPageSequenceMaster().add(createSimplePageMaster(sectionName + "-simple", section.getPageDimensions(), "simple", true, true));
|
||||
lms.getSimplePageMasterOrPageSequenceMaster().add(createPageSequenceMaster(hf, sectionName));
|
||||
}
|
||||
return lms;
|
||||
}
|
||||
|
||||
private static PageSequenceMaster createPageSequenceMaster(HeaderFooterPolicy hf, String sectionName) {
|
||||
boolean noHeadersFootersAfterFirstPage = true;
|
||||
PageSequenceMaster psm = getFactory().createPageSequenceMaster();
|
||||
psm.setMasterName(sectionName);
|
||||
RepeatablePageMasterAlternatives rpma = getFactory().createRepeatablePageMasterAlternatives();
|
||||
psm.getSinglePageMasterReferenceOrRepeatablePageMasterReferenceOrRepeatablePageMasterAlternatives().add(rpma);
|
||||
if (hf.getFirstHeader() != null || hf.getFirstFooter() != null) {
|
||||
ConditionalPageMasterReference cpmr1 = getFactory().createConditionalPageMasterReference();
|
||||
cpmr1.setMasterReference(sectionName + "-firstpage");
|
||||
cpmr1.setPagePosition(PagePositionType.FIRST);
|
||||
rpma.getConditionalPageMasterReference().add(cpmr1);
|
||||
}
|
||||
if (hf.getEvenHeader() != null || hf.getEvenFooter() != null) {
|
||||
ConditionalPageMasterReference cpmr2 = getFactory().createConditionalPageMasterReference();
|
||||
cpmr2.setMasterReference(sectionName + "-evenpage");
|
||||
cpmr2.setOddOrEven(OddOrEvenType.EVEN);
|
||||
rpma.getConditionalPageMasterReference().add(cpmr2);
|
||||
ConditionalPageMasterReference cpmr3 = getFactory().createConditionalPageMasterReference();
|
||||
cpmr3.setMasterReference(sectionName + "-default");
|
||||
cpmr3.setOddOrEven(OddOrEvenType.ODD);
|
||||
rpma.getConditionalPageMasterReference().add(cpmr3);
|
||||
noHeadersFootersAfterFirstPage = false;
|
||||
} else if (hf.getDefaultHeader() != null || hf.getDefaultFooter() != null) {
|
||||
ConditionalPageMasterReference cpmr4 = getFactory().createConditionalPageMasterReference();
|
||||
cpmr4.setMasterReference(sectionName + "-default");
|
||||
rpma.getConditionalPageMasterReference().add(cpmr4);
|
||||
noHeadersFootersAfterFirstPage = false;
|
||||
}
|
||||
if (noHeadersFootersAfterFirstPage) {
|
||||
ConditionalPageMasterReference cpmr5 = getFactory().createConditionalPageMasterReference();
|
||||
cpmr5.setMasterReference(sectionName + "-simple");
|
||||
rpma.getConditionalPageMasterReference().add(cpmr5);
|
||||
}
|
||||
return psm;
|
||||
}
|
||||
|
||||
private static SimplePageMaster createSimplePageMaster(String masterName, PageDimensions page, String appendRegionName, boolean needBefore, boolean needAfter) {
|
||||
SimplePageMaster spm = getFactory().createSimplePageMaster();
|
||||
spm.setMasterName(masterName);
|
||||
spm.setPageHeight(UnitsOfMeasurement.twipToBest(page.getPgSz().getH().intValue()));
|
||||
spm.setPageWidth(UnitsOfMeasurement.twipToBest(page.getPgSz().getW().intValue()));
|
||||
spm.setMarginLeft(UnitsOfMeasurement.twipToBest(page.getPgMar().getLeft().intValue()));
|
||||
spm.setMarginRight(UnitsOfMeasurement.twipToBest(page.getPgMar().getRight().intValue()));
|
||||
RegionBody rb = getFactory().createRegionBody();
|
||||
rb.setMarginLeft("0mm");
|
||||
rb.setMarginRight("0mm");
|
||||
float halfPageHeight = (float)(page.getPgSz().getH().intValue() / 40);
|
||||
String halfPageHeightPts = halfPageHeight + "pt";
|
||||
spm.setRegionBody(rb);
|
||||
if (needBefore) {
|
||||
RegionBefore rBefore = getFactory().createRegionBefore();
|
||||
rBefore.setRegionName("xsl-region-before-" + appendRegionName);
|
||||
spm.setRegionBefore(rBefore);
|
||||
int marginTopTwips = page.getHeaderMargin();
|
||||
spm.setMarginTop(UnitsOfMeasurement.twipToBest(marginTopTwips));
|
||||
rBefore.setExtent(halfPageHeightPts);
|
||||
rb.setMarginTop(halfPageHeightPts);
|
||||
} else {
|
||||
spm.setMarginTop(UnitsOfMeasurement.twipToBest(page.getPgMar().getTop().intValue()));
|
||||
}
|
||||
if (needAfter) {
|
||||
RegionAfter rAfter = getFactory().createRegionAfter();
|
||||
rAfter.setRegionName("xsl-region-after-" + appendRegionName);
|
||||
spm.setRegionAfter(rAfter);
|
||||
int marginBottomTwips = page.getFooterMargin();
|
||||
spm.setMarginBottom(UnitsOfMeasurement.twipToBest(marginBottomTwips));
|
||||
rAfter.setExtent(halfPageHeightPts);
|
||||
rb.setMarginBottom(halfPageHeightPts);
|
||||
} else {
|
||||
spm.setMarginBottom(UnitsOfMeasurement.twipToBest(page.getPgMar().getBottom().intValue()));
|
||||
}
|
||||
return spm;
|
||||
}
|
||||
|
||||
private static ObjectFactory getFactory() {
|
||||
if (factory == null)
|
||||
factory = new ObjectFactory();
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
package org.docx4j.convert.out.fo;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
public class PlaceholderReplacementHandler extends DefaultHandler {
|
||||
protected PlaceholderLookup placeholderLookup = null;
|
||||
|
||||
protected DefaultHandler defaultHandler = null;
|
||||
|
||||
protected StringBuilder buffer = new StringBuilder();
|
||||
|
||||
protected char[] tmpCharArray = new char[10240];
|
||||
|
||||
public PlaceholderReplacementHandler(DefaultHandler defaultHandler, PlaceholderLookup variableLookup) {
|
||||
this.placeholderLookup = variableLookup;
|
||||
this.defaultHandler = defaultHandler;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.defaultHandler.hashCode();
|
||||
}
|
||||
|
||||
public InputSource resolveEntity(String publicId, String systemId) throws IOException, SAXException {
|
||||
return this.defaultHandler.resolveEntity(publicId, systemId);
|
||||
}
|
||||
|
||||
public void notationDecl(String name, String publicId, String systemId) throws SAXException {
|
||||
this.defaultHandler.notationDecl(name, publicId, systemId);
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
return this.defaultHandler.equals(obj);
|
||||
}
|
||||
|
||||
public void unparsedEntityDecl(String name, String publicId, String systemId, String notationName) throws SAXException {
|
||||
this.defaultHandler.unparsedEntityDecl(name, publicId, systemId, notationName);
|
||||
}
|
||||
|
||||
public void setDocumentLocator(Locator locator) {
|
||||
this.defaultHandler.setDocumentLocator(locator);
|
||||
}
|
||||
|
||||
public void startDocument() throws SAXException {
|
||||
this.defaultHandler.startDocument();
|
||||
}
|
||||
|
||||
public void endDocument() throws SAXException {
|
||||
this.defaultHandler.endDocument();
|
||||
}
|
||||
|
||||
public void startPrefixMapping(String prefix, String uri) throws SAXException {
|
||||
this.defaultHandler.startPrefixMapping(prefix, uri);
|
||||
}
|
||||
|
||||
public void endPrefixMapping(String prefix) throws SAXException {
|
||||
this.defaultHandler.endPrefixMapping(prefix);
|
||||
}
|
||||
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||
this.defaultHandler.startElement(uri, localName, qName, attributes);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.defaultHandler.toString();
|
||||
}
|
||||
|
||||
public void endElement(String uri, String localName, String qName) throws SAXException {
|
||||
if (this.buffer.length() > 0) {
|
||||
if (this.placeholderLookup.hasPlaceholders(this.buffer))
|
||||
this.placeholderLookup.replaceValues(this.buffer);
|
||||
if (this.buffer.length() > 0) {
|
||||
if (this.buffer.length() > this.tmpCharArray.length)
|
||||
this.tmpCharArray = new char[(this.buffer.length() / 1024 + 1) * 1024];
|
||||
this.buffer.getChars(0, this.buffer.length(), this.tmpCharArray, 0);
|
||||
this.defaultHandler.characters(this.tmpCharArray, 0, this.buffer.length());
|
||||
this.buffer.setLength(0);
|
||||
}
|
||||
}
|
||||
this.defaultHandler.endElement(uri, localName, qName);
|
||||
}
|
||||
|
||||
public void characters(char[] ch, int start, int length) throws SAXException {
|
||||
this.buffer.append(ch, start, length);
|
||||
}
|
||||
|
||||
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
|
||||
this.defaultHandler.ignorableWhitespace(ch, start, length);
|
||||
}
|
||||
|
||||
public void processingInstruction(String target, String data) throws SAXException {
|
||||
this.defaultHandler.processingInstruction(target, data);
|
||||
}
|
||||
|
||||
public void skippedEntity(String name) throws SAXException {
|
||||
this.defaultHandler.skippedEntity(name);
|
||||
}
|
||||
|
||||
public void warning(SAXParseException e) throws SAXException {
|
||||
this.defaultHandler.warning(e);
|
||||
}
|
||||
|
||||
public void error(SAXParseException e) throws SAXException {
|
||||
this.defaultHandler.error(e);
|
||||
}
|
||||
|
||||
public void fatalError(SAXParseException e) throws SAXException {
|
||||
this.defaultHandler.fatalError(e);
|
||||
}
|
||||
|
||||
public static interface PlaceholderLookup {
|
||||
boolean hasPlaceholders(StringBuilder param1StringBuilder);
|
||||
|
||||
void replaceValues(StringBuilder param1StringBuilder);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
package org.docx4j.convert.out.fo;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.docx4j.convert.out.common.AbstractWmlConversionContext;
|
||||
import org.docx4j.convert.out.common.Writer;
|
||||
import org.docx4j.convert.out.common.writer.AbstractSymbolWriter;
|
||||
import org.docx4j.fonts.PhysicalFont;
|
||||
import org.docx4j.fonts.fop.fonts.Typeface;
|
||||
import org.docx4j.wml.R;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
public class SymbolWriter extends AbstractSymbolWriter {
|
||||
private static final Logger log = LoggerFactory.getLogger(SymbolWriter.class);
|
||||
|
||||
public Node toNode(AbstractWmlConversionContext context, Object unmarshalledNode, Node modelContent, Writer.TransformState state, Document doc) throws TransformerException {
|
||||
R.Sym modelData = (R.Sym)unmarshalledNode;
|
||||
String fontName = modelData.getFont();
|
||||
String textValue = modelData.getChar();
|
||||
PhysicalFont pf = context.getWmlPackage().getFontMapper().get(fontName);
|
||||
char chValue = '\000';
|
||||
Typeface typeface = null;
|
||||
if (pf != null) {
|
||||
typeface = pf.getTypeface();
|
||||
if (typeface != null) {
|
||||
if (textValue.length() > 1) {
|
||||
try {
|
||||
chValue = (char)Integer.parseInt(textValue, 16);
|
||||
} catch (NumberFormatException nfe) {
|
||||
chValue = '\000';
|
||||
}
|
||||
} else {
|
||||
chValue = textValue.charAt(0);
|
||||
}
|
||||
if (chValue != '\000') {
|
||||
if (chValue > '')
|
||||
chValue = (char)(chValue - 61440);
|
||||
if (typeface.mapChar(chValue) == '\000') {
|
||||
chValue = (char)(chValue + 61440);
|
||||
if (typeface.mapChar(chValue) == '\000')
|
||||
chValue = '\000';
|
||||
}
|
||||
if (chValue != '\000')
|
||||
textValue = Character.toString(chValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
Text theChar = doc.createTextNode(textValue);
|
||||
DocumentFragment docfrag = doc.createDocumentFragment();
|
||||
if (pf == null) {
|
||||
log.warn("No physical font present for:" + fontName);
|
||||
docfrag.appendChild(theChar);
|
||||
} else {
|
||||
Element foInline = doc.createElementNS("http://www.w3.org/1999/XSL/Format", "fo:inline");
|
||||
docfrag.appendChild(foInline);
|
||||
foInline.setAttribute("font-family", pf.getName());
|
||||
foInline.appendChild(theChar);
|
||||
}
|
||||
return docfrag;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue