private static SdtBlock createSdt(String tagVal, RPr rPr) { // .. so create content control! SdtBlock sdtBlock = Context.getWmlObjectFactory().createSdtBlock(); SdtPr sdtPr = Context.getWmlObjectFactory().createSdtPr(); sdtBlock.setSdtPr(sdtPr); SdtContentBlock sdtContent = Context.getWmlObjectFactory().createSdtContentBlock(); sdtBlock.setSdtContent(sdtContent); // For borders/shading, we'll use the values in this first paragraph. // We'll use a tag, so the XSLT can detect that its supposed to do something special. Tag tag = Context.getWmlObjectFactory().createTag(); tag.setVal(tagVal); sdtPr.setTag(tag); if (rPr != null) { sdtPr.getRPrOrAliasOrLock().add((RPr) XmlUtils.deepCopy(rPr)); /* * ECMA-376 says "specifies the set of run properties which shall be applied to * the text entered into the parent structured document tag in replacement of * placeholder text. When placeholder text is present in a structured document * tag, its formatting is often different than the desired underlying formatting, * and this element specifies the formatting which shall be used for non-placeholder * text contents when they are initially added to the control. " * * Note that docx2fo.xslt is co-opting this to do something else. */ } return sdtBlock; }
private List<Object> cloneRepeatSdt(Object sdt, String xpathBase, int numRepeats) { List<Object> newContent = new ArrayList<Object>(); SdtPr sdtPr = getSdtPr(sdt); log.debug(XmlUtils.marshaltoString(sdtPr, true, true)); // CTDataBinding binding = // (CTDataBinding)XmlUtils.unwrap(sdtPr.getDataBinding()); CTDataBinding binding = sdtPr.getDataBinding(); if (binding != null) { // Shouldn't be a binding anyway sdtPr.getRPrOrAliasOrLock().remove(binding); } emptyRepeatTagValue(sdtPr.getTag()); // 2012 07 15: do it to the first one for (int i = 0; i < numRepeats; i++) { // 2012 07 13: for "od:RptPosCon" processing to // work (conditional inclusion dependant on position // in repeat), we need each entry (ie including the // original) to have the same tag (which I've changed // to od:rptd). if (i > 0) { // Change ID sdtPr.setId(); } // preserve ID on index 0, important for OpenDoPEReverter! // Clone newContent.add(XmlUtils.deepCopy(sdt)); } return newContent; }
/** * Insert an empty placeholder SDT, to facilitate round-tripping (ie ability to convert instance * docx back to original template), which you may wish to do if you want to insert updated data, * but preserve certain manual edits. * * @param sdt * @return */ private List<Object> repeatZero(Object sdt) { List<Object> newContent = new ArrayList<Object>(); // if (removeSdtCellsOnFailedCondition) { // // backward compatibility // // NB this is not compatible with reverting functionality, and // // will break if the result is an empty tc // return newContent; // } newContent.add(sdt); // Change the tag to od:resultRepeatZero SdtPr sdtPr = getSdtPr(sdt); CTDataBinding binding = sdtPr.getDataBinding(); if (binding != null) { // Shouldn't be a binding anyway sdtPr.getRPrOrAliasOrLock().remove(binding); } Tag tag = sdtPr.getTag(); final String tagVal = tag.getVal(); final Pattern stripRepeatArgPattern = Pattern.compile("(.*od:repeat=)([^&]*)(.*)"); final Matcher stripPatternMatcher = stripRepeatArgPattern.matcher(tagVal); if (!stripPatternMatcher.matches()) { log.error( "Cannot find repeat tag in sdtPr/tag while processing repeat; something is wrong with " + tagVal); return newContent; } final String emptyRepeatValue = BINDING_RESULT_RPTD_ZERO + "=" + stripPatternMatcher.group(2) + stripPatternMatcher.group(3); tag.setVal(emptyRepeatValue); // Lock it CTLock lock = Context.getWmlObjectFactory().createCTLock(); lock.setVal(org.docx4j.wml.STLock.SDT_CONTENT_LOCKED); JAXBElement<org.docx4j.wml.CTLock> lockWrapped = Context.getWmlObjectFactory().createSdtPrLock(lock); sdtPr.getRPrOrAliasOrLock().add(lockWrapped); // assumes no lock is there already // Empty the content // .. OpenDoPEIntegrity fixes this where it is not OK, but // where it needs to insert a tc, it has no way of adding original tcPr, so // we handle this here TcFinder tcFinder = new TcFinder(); new TraversalUtil(((SdtElement) sdt).getSdtContent().getContent(), tcFinder); if (tcFinder.tcList.size() > 0) { Tc tc = tcFinder.tcList.get(0); tc.getContent().clear(); P p = Context.getWmlObjectFactory().createP(); tc.getContent().add(p); ((SdtElement) sdt).getSdtContent().getContent().clear(); ((SdtElement) sdt).getSdtContent().getContent().add(tc); } else { ((SdtElement) sdt).getSdtContent().getContent().clear(); } return newContent; }
@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; }