protected static List<ConversionSectionWrapper> processComplete( WordprocessingMLPackage wmlPackage, Document document, RelationshipsPart rels, BooleanDefaultTrue evenAndOddHeaders, boolean dummyPageNumbering) { List<ConversionSectionWrapper> conversionSections = new ArrayList<ConversionSectionWrapper>(); List<Object> sectionContent = new ArrayList<Object>(); ConversionSectionWrapper currentSectionWrapper = null; HeaderFooterPolicy previousHF = null; int conversionSectionIndex = 0; // According to the ECMA-376 2ed, if type is not specified, read it as next page // However Word 2007 sometimes treats it as continuous, and sometimes doesn't?? // 20130216 Review above comment: ! In the Word UI, the Word "continuous" is shown where it is // effective. // In the XML, it is stored in the next following sectPr. // First, remove content controls, // since the P could be in a content control. // (It is easier to remove content controls, than // to make the code below TraversalUtil based) // RemovalHandler is an XSLT-based way of doing this, // but here we avoid introducing a dependency on // XSLT (Xalan) for PDF output. SdtBlockFinder sbr = new SdtBlockFinder(); new TraversalUtil(document.getContent(), sbr); for (int i = sbr.sdtBlocks.size() - 1; i >= 0; i--) { // Have to process in reverse order // so that parentList is correct for nested sdt 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()); } // if (log.isDebugEnabled()) { // log.debug(XmlUtils.marshaltoString(document, true, true)); // } // Make a list, so it is easy to look at the following sectPr, // which we need to do to handle continuous sections properly List<SectPr> sectPrs = new ArrayList<SectPr>(); for (Object o : document.getBody().getContent()) { if (o instanceof org.docx4j.wml.P) { if (((org.docx4j.wml.P) o).getPPr() != null) { org.docx4j.wml.PPr ppr = ((org.docx4j.wml.P) o).getPPr(); if (ppr.getSectPr() != null) { sectPrs.add(ppr.getSectPr()); } } } } if (document.getBody().getSectPr() != null) { // usual case sectPrs.add(document.getBody().getSectPr()); } else { log.debug("No body level sectPr in document"); // OK if the last object is w:p and it contains a sectPr. 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) { // ok log.debug( ".. but last p contains sectPr .. move it"); // so our assumption later about there // being a following section is correct 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()); } } int sectPrIndex = 0; // includes continuous ones for (Object o : document.getBody().getContent()) { if (o instanceof org.docx4j.wml.P) { if (((org.docx4j.wml.P) o).getPPr() != null) { org.docx4j.wml.PPr ppr = ((org.docx4j.wml.P) o).getPPr(); if (ppr.getSectPr() != null) { // If the *following* section is continuous, don't add *this* section boolean ignoreThisSection = false; SectPr followingSectPr = sectPrs.get(++sectPrIndex); if (followingSectPr.getType() != null && followingSectPr.getType().getVal().equals("continuous")) { ignoreThisSection = true; // If the w:pgSz on the two sections differs, // then Word inserts a page break (ie doesn't treat it as continuous). // If no w:pgSz element is present, then Word defaults // (presumably to Legal? TODO CHECK. There is no default setting in the docx). // Word always inserts a w:pgSz element? PgSz pgSzThis = ppr.getSectPr().getPgSz(); PgSz pgSzNext = followingSectPr.getPgSz(); if (pgSzThis != null && pgSzNext != null) { if (pgSzThis.getH().compareTo(pgSzNext.getH()) != 0) { ignoreThisSection = false; } if (pgSzThis.getW().compareTo(pgSzNext.getW()) != 0) { ignoreThisSection = false; } // Orientation:default is portrait 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) { ignoreThisSection = false; } } // TODO: handle cases where one or both pgSz elements are missing, // or H or W is missing. // Treat pgSz element missing as Legal size? } if (ignoreThisSection) { // In case there are some headers/footers that get inherited by the next section previousHF = new HeaderFooterPolicy(ppr.getSectPr(), previousHF, rels, evenAndOddHeaders); } else { currentSectionWrapper = createSectionWrapper( ppr.getSectPr(), previousHF, rels, evenAndOddHeaders, ++conversionSectionIndex, sectionContent, dummyPageNumbering); conversionSections.add(currentSectionWrapper); previousHF = currentSectionWrapper.getHeaderFooterPolicy(); sectionContent = new ArrayList<Object>(); } } } } sectionContent.add(o); // System.out.println(XmlUtils.marshaltoString(o, true)); } currentSectionWrapper = createSectionWrapper( document.getBody().getSectPr(), previousHF, rels, evenAndOddHeaders, ++conversionSectionIndex, sectionContent, dummyPageNumbering); conversionSections.add(currentSectionWrapper); return conversionSections; }
@Override public List<Object> apply(Object o) { // NB: the tests in this method have to be comprehensive, // so if support for glow etc is introduced, tests for those // will need to be added if (o instanceof org.docx4j.wml.P) { P p = (P) o; // W14? if (p.getParaId() != null) { needW14 = true; } // W15? if (!needW15) { PPr ppr = p.getPPr(); if (ppr != null) { if (ppr.getCollapsed() != null) { needW15 = true; } if (ppr.getSectPr() != null && ppr.getSectPr().getFootnoteColumns() != null) { needW15 = true; } } } } else if (o instanceof SdtElement) { SdtPr sdtPr = ((SdtElement) o).getSdtPr(); if (sdtPr != null) { if (contains( sdtPr.getRPrOrAliasOrLock(), "http://schemas.microsoft.com/office/word/2010/wordml", w14SdtPrNames)) { needW14 = true; } if (contains( sdtPr.getRPrOrAliasOrLock(), "http://schemas.microsoft.com/office/word/2012/wordml", w15SdtPrNames)) { needW15 = true; } } } else if (o instanceof Tr) { // TODO does this need to be unwrapped? if (((Tr) o).getParaId() != null) { needW14 = true; } } else if (o instanceof CTObject) { if (((CTObject) o).getAnchorId() != null) { needW14 = true; } } else if (o instanceof Pict) { if (((Pict) o).getAnchorId() != null) { needW14 = true; } } return null; }