/*
* Copyright 2007-2008, Plutext Pty Ltd.
*
* This file is part of docx4j.
docx4j is licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package org.docx4j.samples;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import org.docx4j.XmlUtils;
import org.docx4j.convert.out.flatOpcXml.FlatOpcXmlCreator;
import org.docx4j.convert.out.html.AbstractHtmlExporter;
import org.docx4j.jaxb.Context;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* The idea here was to display a docx
* in the browser by converting it to
* Flat OPC XML, then applying CSS to it.
*
* @author jharrop
*
*/
public class CreateXmlCss {
public final static String HTML_TOP = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">"
+"\n<html>"
+"\n<head>"
+"\n<style type=\"text/css\">";
public final static String CSS_FOR_TABLES = "\n\n/* TABLE STYLES */"
+ "\n.table { display:table; table-layout:fixed; border-color: #600; border-style: solid; border-width: 0 0 1px 1px; border-spacing: 0; border-collapse: collapse;}"
+ "\n.tr { display:table-row;}"
+ "\n.td { display:table-cell; border-color: #600; border-style: solid; margin: 0; padding: 4px; border-width: 1px 1px 0 0; background-color: #FFC;}\n";
public final static String HTML_MIDDLE = "</style>"
+ "\n</head>\n<body>";
public final static String HTML_TAIL = "\n </body>"
+ "\n <script type=\"text/javascript\" src=\"javeline_xpath.js\"></script>"
+ "\n <script type=\"text/javascript\" src=\"wml_fix.js\"></script>"
+ "\n</html>";
public static void main(String[] args)
throws Exception {
boolean save = true;
// If you want to be able to display non-external images,
// or you are extending wml_fix.js to do client-side
// style resolution, you'll want to embed the entire
// Flat OPC, rather than just document.xml
boolean useFlatOPC = true;
// String inputfilepath = System.getProperty("user.dir") + "/sample-docs/numbering-multilevel.docx";
//String inputfilepath = System.getProperty("user.dir") + "/test3.docx";
// String inputfilepath = "/home/dev/workspace/docx4all/sample-docs/docx4all-CurrentDocxFeatures.docx";
String inputfilepath = "/home/dev/workspace/docx4j/sample-docs/StyleResolution.xml";
System.out.println(inputfilepath);
WordprocessingMLPackage wordMLPackage;
org.docx4j.xmlPackage.Package flatOPC = null;
if (inputfilepath.endsWith(".xml")) {
JAXBContext jc = Context.jcXmlPackage;
Unmarshaller u = jc.createUnmarshaller();
u.setEventHandler(new org.docx4j.jaxb.JaxbValidationEventHandler());
flatOPC = (org.docx4j.xmlPackage.Package)((JAXBElement)u.unmarshal(
new javax.xml.transform.stream.StreamSource(new FileInputStream(inputfilepath)))).getValue();
org.docx4j.convert.in.FlatOpcXmlImporter xmlPackage = new org.docx4j.convert.in.FlatOpcXmlImporter( flatOPC);
wordMLPackage = (WordprocessingMLPackage)xmlPackage.get();
} else {
wordMLPackage = WordprocessingMLPackage.load(new java.io.File(inputfilepath));
}
// Convert it to HTML (ie no self-closing tags)
Object o;
Document doc;
if (useFlatOPC) {
if (flatOPC==null) {
// We must have started with a .docx
FlatOpcXmlCreator worker = new FlatOpcXmlCreator(wordMLPackage);
o = worker.get();
} else {
o = flatOPC;
}
doc = XmlUtils.marshaltoW3CDomDocument(o, Context.jcXmlPackage);
} else {
o = wordMLPackage.getMainDocumentPart().getJaxbElement();
doc = XmlUtils.marshaltoW3CDomDocument(o);
}
StringBuffer buff = new StringBuffer();
serialise(doc, buff, " " );
// Generate CSS
String css_other = AbstractHtmlExporter.getCssForStyles(wordMLPackage);
// Join it all together
String result = HTML_TOP + CSS_FOR_TABLES + css_other + HTML_MIDDLE + buff.toString() + HTML_TAIL;
OutputStream os;
if (save) {
os = new java.io.FileOutputStream(inputfilepath + ".html");
} else {
os = System.out;
}
os.write(result.getBytes());
os.close();
if (save) {
System.out.println("Saved: " + inputfilepath + ".html ");
}
}
public static void serialise( Node sourceNode, StringBuffer result, String indent ) {
//log.debug("node type" + sourceNode.getNodeType());
switch (sourceNode.getNodeType() ) {
case Node.DOCUMENT_NODE: // type 9
// recurse on each child
NodeList nodes = sourceNode.getChildNodes();
if (nodes != null) {
for (int i=0; i<nodes.getLength(); i++) {
serialise((Node)nodes.item(i), result, indent);
}
}
break;
case Node.ELEMENT_NODE:
// Copy of the node itself
result.append("\n" + indent + "<" + sourceNode.getNodeName() );
// .. its attributes
NamedNodeMap atts = sourceNode.getAttributes();
for (int i = 0 ; i < atts.getLength() ; i++ ) {
Attr attr = (Attr)atts.item(i);
// if (attr.getNamespaceURI()!=null
// && attr.getNamespaceURI().equals("http://www.w3.org/2000/xmlns/")) {
// result.append(" " + attr.getLocalName() + "=\"" + attr.getValue() + "\"");
// } else {
// result.append(" " + attr.getName() + "=\"" + attr.getValue() + "\"");
// }
result.append(" " + attr.getName() + "=\"" + attr.getValue() + "\"");
}
result.append(">");
if (sourceNode.getChildNodes() == null
|| sourceNode.getChildNodes().getLength() ==0) {
// this is where we force tags to be
// non self-closing
result.append("</" + sourceNode.getNodeName() + ">" );
} else {
// recurse on each child
NodeList children = sourceNode.getChildNodes();
boolean hasNonTextChild = false;
if (children != null) {
for (int i=0; i<children.getLength(); i++) {
//treeCopy( (DTMNodeProxy)children.item(i), newChild);
if (children.item(i).getNodeType() != Node.TEXT_NODE) {
hasNonTextChild = true;
}
serialise( (Node)children.item(i), result, indent+ " ");
}
}
if (hasNonTextChild) {
result.append("\n" + indent);
}
result.append("</" + sourceNode.getNodeName() + ">" );
}
break;
case Node.TEXT_NODE:
//Node textNode = destParent.getOwnerDocument().createTextNode(sourceNode.getNodeValue());
result.append(sourceNode.getNodeValue());
break;
// case Node.CDATA_SECTION_NODE:
// writer.write("<![CDATA[" +
// node.getNodeValue() + "]]>");
// break;
//
// case Node.COMMENT_NODE:
// writer.write(indentLevel + "<!-- " +
// node.getNodeValue() + " -->");
// writer.write(lineSeparator);
// break;
//
// case Node.PROCESSING_INSTRUCTION_NODE:
// writer.write("<?" + node.getNodeName() +
// " " + node.getNodeValue() +
// "?>");
// writer.write(lineSeparator);
// break;
//
// case Node.ENTITY_REFERENCE_NODE:
// writer.write("&" + node.getNodeName() + ";");
// break;
//
// case Node.DOCUMENT_TYPE_NODE:
// DocumentType docType = (DocumentType)node;
// writer.write("<!DOCTYPE " + docType.getName());
// if (docType.getPublicId() != null) {
// System.out.print(" PUBLIC \"" +
// docType.getPublicId() + "\" ");
// } else {
// writer.write(" SYSTEM ");
// }
// writer.write("\"" + docType.getSystemId() + "\">");
// writer.write(lineSeparator);
// break;
}
}
}