package org.docx4j.convert.out.html; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.math.BigInteger; import javax.xml.bind.JAXBElement; import org.docx4j.Docx4J; import org.docx4j.Docx4jProperties; import org.docx4j.XmlUtils; import org.docx4j.convert.out.HTMLSettings; import org.docx4j.jaxb.Context; import org.docx4j.openpackaging.exceptions.Docx4JException; import org.docx4j.openpackaging.packages.WordprocessingMLPackage; import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart; import org.docx4j.openpackaging.parts.WordprocessingML.NumberingDefinitionsPart; import org.docx4j.wml.Numbering; import org.docx4j.wml.P; import org.docx4j.wml.PPr; import org.docx4j.wml.PPrBase; import org.docx4j.wml.R; import org.docx4j.wml.SdtBlock; import org.docx4j.wml.SdtContentBlock; import org.docx4j.wml.Tbl; import org.docx4j.wml.Tc; import org.docx4j.wml.Text; import org.docx4j.wml.Tr; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ListsToContentControlsTest { protected static Logger log = LoggerFactory.getLogger(ListsToContentControls.class); // same logger private static org.docx4j.wml.ObjectFactory wmlObjectFactory = Context.getWmlObjectFactory(); @Test public void singleList() throws Exception { WordprocessingMLPackage wordMLPackage = createPkg(); MainDocumentPart mdp = wordMLPackage.getMainDocumentPart(); mdp.getContent().add(createUnnumberedP()); mdp.getContent().add(createNumberedP(1,0)); mdp.getContent().add(createNumberedP(1,0)); mdp.getContent().add(createUnnumberedP()); //wordMLPackage.save(new File(System.getProperty("user.dir") + "/OUT_simpleTest.docx")); ListsToContentControls.process(wordMLPackage); System.out.println(mdp.getXML()); } @Test public void singleListTwice() throws Exception { WordprocessingMLPackage wordMLPackage = createPkg(); MainDocumentPart mdp = wordMLPackage.getMainDocumentPart(); mdp.getContent().add(createUnnumberedP()); mdp.getContent().add(createNumberedP(1,0)); mdp.getContent().add(createNumberedP(1,0)); mdp.getContent().add(createUnnumberedP()); mdp.getContent().add(createNumberedP(1,0)); mdp.getContent().add(createNumberedP(1,0)); mdp.getContent().add(createUnnumberedP()); //wordMLPackage.save(new File(System.getProperty("user.dir") + "/OUT_simpleTest.docx")); ListsToContentControls.process(wordMLPackage); System.out.println(mdp.getXML()); } @Test public void singleList2Levels() throws Exception { WordprocessingMLPackage wordMLPackage = createPkg(); MainDocumentPart mdp = wordMLPackage.getMainDocumentPart(); mdp.getContent().add(createUnnumberedP()); mdp.getContent().add(createNumberedP(1,0)); mdp.getContent().add(createNumberedP(1,1)); // nested mdp.getContent().add(createUnnumberedP()); //wordMLPackage.save(new File(System.getProperty("user.dir") + "/OUT_simpleTest.docx")); ListsToContentControls.process(wordMLPackage); System.out.println(mdp.getXML()); } @Test public void singleList2LevelsPop() throws Exception { WordprocessingMLPackage wordMLPackage = createPkg(); MainDocumentPart mdp = wordMLPackage.getMainDocumentPart(); mdp.getContent().add(createUnnumberedP()); mdp.getContent().add(createNumberedP(1,0)); mdp.getContent().add(createNumberedP(1,1)); // nested mdp.getContent().add(createNumberedP(1,0)); // then back mdp.getContent().add(createUnnumberedP()); //wordMLPackage.save(new File(System.getProperty("user.dir") + "/OUT_simpleTest.docx")); ListsToContentControls.process(wordMLPackage); System.out.println(mdp.getXML()); } @Test public void singleListStartLvl2() throws Exception { WordprocessingMLPackage wordMLPackage = createPkg(); MainDocumentPart mdp = wordMLPackage.getMainDocumentPart(); mdp.getContent().add(createUnnumberedP()); mdp.getContent().add(createNumberedP(1,1)); mdp.getContent().add(createNumberedP(1,0)); mdp.getContent().add(createNumberedP(1,2)); mdp.getContent().add(createUnnumberedP()); //wordMLPackage.save(new File(System.getProperty("user.dir") + "/OUT_simpleTest.docx")); ListsToContentControls.process(wordMLPackage); System.out.println(mdp.getXML()); } @Test public void twoLists() throws Exception { WordprocessingMLPackage wordMLPackage = createPkg(); MainDocumentPart mdp = wordMLPackage.getMainDocumentPart(); mdp.getContent().add(createUnnumberedP()); mdp.getContent().add(createNumberedP(1,0)); mdp.getContent().add(createNumberedP(2,0)); mdp.getContent().add(createUnnumberedP()); //wordMLPackage.save(new File(System.getProperty("user.dir") + "/OUT_simpleTest.docx")); ListsToContentControls.process(wordMLPackage); System.out.println(mdp.getXML()); } @Test public void existingControl() throws Exception { WordprocessingMLPackage wordMLPackage = createPkg(); MainDocumentPart mdp = wordMLPackage.getMainDocumentPart(); SdtBlock sdtBlock = new SdtBlock(); SdtContentBlock sdtContentBlock = new SdtContentBlock(); sdtBlock.setSdtContent(sdtContentBlock); mdp.getContent().add(sdtBlock); sdtBlock.getSdtContent().getContent().add(createUnnumberedP()); sdtBlock.getSdtContent().getContent().add(createNumberedP(1,0)); sdtBlock.getSdtContent().getContent().add(createNumberedP(1,0)); sdtBlock.getSdtContent().getContent().add(createUnnumberedP()); ListsToContentControls.process(wordMLPackage); System.out.println(mdp.getXML()); } @Test public void tableCell() throws Exception { WordprocessingMLPackage wordMLPackage = createPkg(); MainDocumentPart mdp = wordMLPackage.getMainDocumentPart(); org.docx4j.wml.ObjectFactory wmlObjectFactory = new org.docx4j.wml.ObjectFactory(); Tbl tbl = wmlObjectFactory.createTbl(); JAXBElement<org.docx4j.wml.Tbl> tblWrapped = wmlObjectFactory.createCTFtnEdnTbl(tbl); // Create object for tr Tr tr = wmlObjectFactory.createTr(); tbl.getContent().add( tr); // Create object for tc (wrapped in JAXBElement) Tc tc = wmlObjectFactory.createTc(); JAXBElement<org.docx4j.wml.Tc> tcWrapped = wmlObjectFactory.createTrTc(tc); tr.getContent().add( tcWrapped); mdp.getContent().add(tbl); tc.getContent().add(createUnnumberedP()); tc.getContent().add(createNumberedP(1,0)); tc.getContent().add(createNumberedP(1,0)); tc.getContent().add(createUnnumberedP()); ListsToContentControls.process(wordMLPackage); System.out.println(mdp.getXML()); } @Test public void EndToEnd() throws Exception { WordprocessingMLPackage wordMLPackage = createPkg(); MainDocumentPart mdp = wordMLPackage.getMainDocumentPart(); mdp.getContent().add(createUnnumberedP()); mdp.getContent().add(createNumberedP(1,0)); mdp.getContent().add(createNumberedP(2,0)); mdp.getContent().add(createUnnumberedP()); //wordMLPackage.save(new File(System.getProperty("user.dir") + "/OUT_simpleTest.docx")); // ListsToContentControls.process(wordMLPackage); System.out.println(mdp.getXML()); toHTML( wordMLPackage); } private void toHTML(WordprocessingMLPackage wordMLPackage) throws Docx4JException { // Back to XHTML HTMLSettings htmlSettings = Docx4J.createHTMLSettings(); htmlSettings.setWmlPackage(wordMLPackage); // Sample sdt tag handler (tag handlers insert specific // html depending on the contents of an sdt's tag). // This will only have an effect if the sdt tag contains // the string class= SdtWriter.registerTagHandler("HTML_ELEMENT", new SdtToListSdtTagHandler()); // output to an OutputStream. OutputStream os = new ByteArrayOutputStream(); // If you want XHTML output Docx4jProperties.setProperty("docx4j.Convert.Out.HTML.OutputMethodXML", true); Docx4J.toHTML(htmlSettings, os, Docx4J.FLAG_EXPORT_PREFER_XSL); // TODO NON_XSL implementation System.out.println(((ByteArrayOutputStream) os).toString()); } protected P createNumberedP(int numId, int ilvl) { P p = wmlObjectFactory.createP(); // Create object for pPr PPr ppr = wmlObjectFactory.createPPr(); p.setPPr(ppr); // Create object for numPr PPrBase.NumPr pprbasenumpr = wmlObjectFactory.createPPrBaseNumPr(); ppr.setNumPr(pprbasenumpr); // Create object for ilvl PPrBase.NumPr.Ilvl pprbasenumprilvl = wmlObjectFactory.createPPrBaseNumPrIlvl(); pprbasenumpr.setIlvl(pprbasenumprilvl); pprbasenumprilvl.setVal( BigInteger.valueOf( ilvl) ); // Create object for numId PPrBase.NumPr.NumId pprbasenumprnumid = wmlObjectFactory.createPPrBaseNumPrNumId(); pprbasenumpr.setNumId(pprbasenumprnumid); pprbasenumprnumid.setVal( BigInteger.valueOf( numId) ); // Create object for pStyle // PPrBase.PStyle pprbasepstyle = wmlObjectFactory.createPPrBasePStyle(); // ppr.setPStyle(pprbasepstyle); // pprbasepstyle.setVal( "ListParagraph"); // Create object for r R r = wmlObjectFactory.createR(); p.getContent().add( r); // Create object for t (wrapped in JAXBElement) Text text = wmlObjectFactory.createText(); JAXBElement<org.docx4j.wml.Text> textWrapped = wmlObjectFactory.createRT(text); r.getContent().add( textWrapped); text.setValue( "list " + numId + ", ilvl " + ilvl); return p; } protected P createUnnumberedP() { P p = wmlObjectFactory.createP(); R r = wmlObjectFactory.createR(); p.getContent().add( r); // Create object for t (wrapped in JAXBElement) Text text = wmlObjectFactory.createText(); JAXBElement<org.docx4j.wml.Text> textWrapped = wmlObjectFactory.createRT(text); r.getContent().add( textWrapped); text.setValue( "UnnumberedP"); return p; } protected WordprocessingMLPackage createPkg() throws Exception { WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage(); NumberingDefinitionsPart ndp = new NumberingDefinitionsPart(); ndp.setContents((Numbering)XmlUtils.unmarshalString(numbering)); wordMLPackage.getMainDocumentPart().addTargetPart(ndp); return wordMLPackage; } private static final String numbering = "<w:numbering mc:Ignorable=\"w14 wp14\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\">" // Ordered list + "<w:abstractNum w:abstractNumId=\"0\">" + "<w:nsid w:val=\"069653C8\"/>" + "<w:multiLevelType w:val=\"multilevel\"/>" + "<w:tmpl w:val=\"0C09001D\"/>" + "<w:lvl w:ilvl=\"0\">" + "<w:start w:val=\"1\"/>" + "<w:numFmt w:val=\"decimal\"/>" + "<w:lvlText w:val=\"%1)\"/>" + "<w:lvlJc w:val=\"left\"/>" + "<w:pPr>" + "<w:ind w:hanging=\"360\" w:left=\"360\"/>" + "</w:pPr>" + "</w:lvl>" + "<w:lvl w:ilvl=\"1\">" + "<w:start w:val=\"1\"/>" + "<w:numFmt w:val=\"lowerLetter\"/>" + "<w:lvlText w:val=\"%2)\"/>" + "<w:lvlJc w:val=\"left\"/>" + "<w:pPr>" + "<w:ind w:hanging=\"360\" w:left=\"720\"/>" + "</w:pPr>" + "</w:lvl>" + "<w:lvl w:ilvl=\"2\">" + "<w:start w:val=\"1\"/>" + "<w:numFmt w:val=\"lowerRoman\"/>" + "<w:lvlText w:val=\"%3)\"/>" + "<w:lvlJc w:val=\"left\"/>" + "<w:pPr>" + "<w:ind w:hanging=\"360\" w:left=\"1080\"/>" + "</w:pPr>" + "</w:lvl>" + "<w:lvl w:ilvl=\"3\">" + "<w:start w:val=\"1\"/>" + "<w:numFmt w:val=\"decimal\"/>" + "<w:lvlText w:val=\"(%4)\"/>" + "<w:lvlJc w:val=\"left\"/>" + "<w:pPr>" + "<w:ind w:hanging=\"360\" w:left=\"1440\"/>" + "</w:pPr>" + "</w:lvl>" + "<w:lvl w:ilvl=\"4\">" + "<w:start w:val=\"1\"/>" + "<w:numFmt w:val=\"lowerLetter\"/>" + "<w:lvlText w:val=\"(%5)\"/>" + "<w:lvlJc w:val=\"left\"/>" + "<w:pPr>" + "<w:ind w:hanging=\"360\" w:left=\"1800\"/>" + "</w:pPr>" + "</w:lvl>" + "<w:lvl w:ilvl=\"5\">" + "<w:start w:val=\"1\"/>" + "<w:numFmt w:val=\"lowerRoman\"/>" + "<w:lvlText w:val=\"(%6)\"/>" + "<w:lvlJc w:val=\"left\"/>" + "<w:pPr>" + "<w:ind w:hanging=\"360\" w:left=\"2160\"/>" + "</w:pPr>" + "</w:lvl>" + "<w:lvl w:ilvl=\"6\">" + "<w:start w:val=\"1\"/>" + "<w:numFmt w:val=\"decimal\"/>" + "<w:lvlText w:val=\"%7.\"/>" + "<w:lvlJc w:val=\"left\"/>" + "<w:pPr>" + "<w:ind w:hanging=\"360\" w:left=\"2520\"/>" + "</w:pPr>" + "</w:lvl>" + "<w:lvl w:ilvl=\"7\">" + "<w:start w:val=\"1\"/>" + "<w:numFmt w:val=\"lowerLetter\"/>" + "<w:lvlText w:val=\"%8.\"/>" + "<w:lvlJc w:val=\"left\"/>" + "<w:pPr>" + "<w:ind w:hanging=\"360\" w:left=\"2880\"/>" + "</w:pPr>" + "</w:lvl>" + "<w:lvl w:ilvl=\"8\">" + "<w:start w:val=\"1\"/>" + "<w:numFmt w:val=\"lowerRoman\"/>" + "<w:lvlText w:val=\"%9.\"/>" + "<w:lvlJc w:val=\"left\"/>" + "<w:pPr>" + "<w:ind w:hanging=\"360\" w:left=\"3240\"/>" + "</w:pPr>" + "</w:lvl>" + "</w:abstractNum>" // Unordered (bulleted) list + "<w:abstractNum w:abstractNumId=\"1\">" + "<w:nsid w:val=\"38572E21\"/>" + "<w:multiLevelType w:val=\"multilevel\"/>" + "<w:tmpl w:val=\"0C090021\"/>" + "<w:lvl w:ilvl=\"0\">" + "<w:start w:val=\"1\"/>" + "<w:numFmt w:val=\"bullet\"/>" + "<w:lvlText w:val=\"\"/>" + "<w:lvlJc w:val=\"left\"/>" + "<w:pPr>" + "<w:ind w:hanging=\"360\" w:left=\"360\"/>" + "</w:pPr>" + "<w:rPr>" + "<w:rFonts w:ascii=\"Wingdings\" w:hAnsi=\"Wingdings\" w:hint=\"default\"/>" + "</w:rPr>" + "</w:lvl>" + "<w:lvl w:ilvl=\"1\">" + "<w:start w:val=\"1\"/>" + "<w:numFmt w:val=\"bullet\"/>" + "<w:lvlText w:val=\"\"/>" + "<w:lvlJc w:val=\"left\"/>" + "<w:pPr>" + "<w:ind w:hanging=\"360\" w:left=\"720\"/>" + "</w:pPr>" + "<w:rPr>" + "<w:rFonts w:ascii=\"Wingdings\" w:hAnsi=\"Wingdings\" w:hint=\"default\"/>" + "</w:rPr>" + "</w:lvl>" + "<w:lvl w:ilvl=\"2\">" + "<w:start w:val=\"1\"/>" + "<w:numFmt w:val=\"bullet\"/>" + "<w:lvlText w:val=\"\"/>" + "<w:lvlJc w:val=\"left\"/>" + "<w:pPr>" + "<w:ind w:hanging=\"360\" w:left=\"1080\"/>" + "</w:pPr>" + "<w:rPr>" + "<w:rFonts w:ascii=\"Wingdings\" w:hAnsi=\"Wingdings\" w:hint=\"default\"/>" + "</w:rPr>" + "</w:lvl>" + "<w:lvl w:ilvl=\"3\">" + "<w:start w:val=\"1\"/>" + "<w:numFmt w:val=\"bullet\"/>" + "<w:lvlText w:val=\"\"/>" + "<w:lvlJc w:val=\"left\"/>" + "<w:pPr>" + "<w:ind w:hanging=\"360\" w:left=\"1440\"/>" + "</w:pPr>" + "<w:rPr>" + "<w:rFonts w:ascii=\"Symbol\" w:hAnsi=\"Symbol\" w:hint=\"default\"/>" + "</w:rPr>" + "</w:lvl>" + "<w:lvl w:ilvl=\"4\">" + "<w:start w:val=\"1\"/>" + "<w:numFmt w:val=\"bullet\"/>" + "<w:lvlText w:val=\"\"/>" + "<w:lvlJc w:val=\"left\"/>" + "<w:pPr>" + "<w:ind w:hanging=\"360\" w:left=\"1800\"/>" + "</w:pPr>" + "<w:rPr>" + "<w:rFonts w:ascii=\"Symbol\" w:hAnsi=\"Symbol\" w:hint=\"default\"/>" + "</w:rPr>" + "</w:lvl>" + "<w:lvl w:ilvl=\"5\">" + "<w:start w:val=\"1\"/>" + "<w:numFmt w:val=\"bullet\"/>" + "<w:lvlText w:val=\"\"/>" + "<w:lvlJc w:val=\"left\"/>" + "<w:pPr>" + "<w:ind w:hanging=\"360\" w:left=\"2160\"/>" + "</w:pPr>" + "<w:rPr>" + "<w:rFonts w:ascii=\"Wingdings\" w:hAnsi=\"Wingdings\" w:hint=\"default\"/>" + "</w:rPr>" + "</w:lvl>" + "<w:lvl w:ilvl=\"6\">" + "<w:start w:val=\"1\"/>" + "<w:numFmt w:val=\"bullet\"/>" + "<w:lvlText w:val=\"\"/>" + "<w:lvlJc w:val=\"left\"/>" + "<w:pPr>" + "<w:ind w:hanging=\"360\" w:left=\"2520\"/>" + "</w:pPr>" + "<w:rPr>" + "<w:rFonts w:ascii=\"Wingdings\" w:hAnsi=\"Wingdings\" w:hint=\"default\"/>" + "</w:rPr>" + "</w:lvl>" + "<w:lvl w:ilvl=\"7\">" + "<w:start w:val=\"1\"/>" + "<w:numFmt w:val=\"bullet\"/>" + "<w:lvlText w:val=\"\"/>" + "<w:lvlJc w:val=\"left\"/>" + "<w:pPr>" + "<w:ind w:hanging=\"360\" w:left=\"2880\"/>" + "</w:pPr>" + "<w:rPr>" + "<w:rFonts w:ascii=\"Symbol\" w:hAnsi=\"Symbol\" w:hint=\"default\"/>" + "</w:rPr>" + "</w:lvl>" + "<w:lvl w:ilvl=\"8\">" + "<w:start w:val=\"1\"/>" + "<w:numFmt w:val=\"bullet\"/>" + "<w:lvlText w:val=\"\"/>" + "<w:lvlJc w:val=\"left\"/>" + "<w:pPr>" + "<w:ind w:hanging=\"360\" w:left=\"3240\"/>" + "</w:pPr>" + "<w:rPr>" + "<w:rFonts w:ascii=\"Symbol\" w:hAnsi=\"Symbol\" w:hint=\"default\"/>" + "</w:rPr>" + "</w:lvl>" + "</w:abstractNum>" + "<w:num w:numId=\"1\">" + "<w:abstractNumId w:val=\"0\"/>" + "</w:num>" + "<w:num w:numId=\"2\">" + "<w:abstractNumId w:val=\"1\"/>" + "</w:num>" + "</w:numbering>"; }