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; }
@Override public void apply(SdtElement element, Object parent, List<Object> siblings) { System.out.println(); SdtPr sdtPr = element.getSdtPr(); if (sdtPr == null) { System.out.println( callback.indent + element.getClass().getSimpleName() + " [no sdtPr!]" + " (having parent " + parent.getClass().getSimpleName() + ")"); } else { System.out.println( callback.indent + element.getClass().getSimpleName() + " (having parent " + parent.getClass().getSimpleName() + ")"); CTDataBinding binding = (CTDataBinding) XmlUtils.unwrap(sdtPr.getDataBinding()); if (binding != null) { System.out.println(callback.indent + " binding: " + binding.getXpath()); } Tag tag = sdtPr.getTag(); if (tag == null) return; System.out.println(callback.indent + " " + tag.getVal()); HashMap<String, String> map = QueryString.parseQueryString(tag.getVal(), true); String conditionId = map.get(OpenDoPEHandler.BINDING_ROLE_CONDITIONAL); String repeatId = map.get(OpenDoPEHandler.BINDING_ROLE_REPEAT); String xp = map.get(OpenDoPEHandler.BINDING_ROLE_XPATH); if (conditionId != null) { Condition c = ConditionsPart.getConditionById(conditions, conditionId); if (c == null) { System.out.println(callback.indent + " " + "Missing condition " + conditionId); } if (c.getParticle() instanceof org.opendope.conditions.Xpathref) { org.opendope.conditions.Xpathref xpathRef = (Xpathref) c.getParticle(); if (xpathRef == null) { System.out.println( callback.indent + " " + "Condition " + c.getId() + " references a missing xpath!"); } org.opendope.xpaths.Xpaths.Xpath xpath = XPathsPart.getXPathById(xPaths, xpathRef.getId()); if (xpath == null) { System.out.println( callback.indent + " " + "XPath specified in condition '" + c.getId() + "' is missing!"); } else { System.out.println( callback.indent + " " + xpath.getId() + ": " + xpath.getDataBinding().getXpath()); } } else { System.out.println("Complex condition: " + XmlUtils.marshaltoString(c, true, true)); } } else if (repeatId != null) { org.opendope.xpaths.Xpaths.Xpath xpath = XPathsPart.getXPathById(xPaths, repeatId); if (xpath == null) { System.out.println( callback.indent + " " + "XPath specified in repeat '" + repeatId + "' is missing!"); } else { System.out.println( callback.indent + " " + xpath.getId() + ": " + xpath.getDataBinding().getXpath()); } } else if (xp != null) { org.opendope.xpaths.Xpaths.Xpath xpath = XPathsPart.getXPathById(xPaths, xp); if (xpath == null) { System.out.println( callback.indent + " " + "XPath specified with id '" + xp + "' is missing!"); } else { System.out.println( callback.indent + " " + xpath.getId() + ": " + xpath.getDataBinding().getXpath()); } } } }
/** * 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; }
private void processDescendantBindings(Object sdt, String xpathBase, int index) { SdtPr sdtPr = getSdtPr(sdt); // log.debug(XmlUtils.marshaltoString(sdtPr, true, true)); // Give it a unique ID (supersedes above?) sdtPr.setId(); // log.debug(XmlUtils.marshaltoString(sdtPr, true, true)); CTDataBinding binding = (CTDataBinding) XmlUtils.unwrap(sdtPr.getDataBinding()); String thisXPath = null; // It'll have one of these three... String conditionId = null; String repeatId = null; String bindingId = null; org.opendope.xpaths.Xpaths.Xpath xpathObj = null; Tag tag = sdtPr.getTag(); if (tag == null) return; HashMap<String, String> map = QueryString.parseQueryString(tag.getVal(), true); if (binding == null) { conditionId = map.get(BINDING_ROLE_CONDITIONAL); repeatId = map.get(BINDING_ROLE_REPEAT); if (conditionId != null) { // c = ConditionsPart.getConditionById(conditions, conditionId); // if (c == null) { // log.error("Missing condition " + conditionId); // throw new InputIntegrityException("Required condition '" + conditionId + "' is // missing"); // } // // // TODO: this code assumes the condition contains // // a simple xpath // log.debug("Using condition" // + XmlUtils.marshaltoString(c, true, true)); // xpathObj = getXPathFromCondition(c); // thisXPath = xpathObj.getDataBinding().getXpath(); processDescendantCondition(sdt, xpathBase, index, tag); return; } else if (repeatId != null) { xpathObj = XPathsPart.getXPathById(xPaths, repeatId); thisXPath = xpathObj.getDataBinding().getXpath(); } else if (map.containsKey(BINDING_CONTENTTYPE) || map.containsKey(BINDING_HANDLER) || map.containsKey(BINDING_PROGID)) { xpathObj = XPathsPart.getXPathById(xPaths, map.get(BINDING_ROLE_XPATH)); thisXPath = xpathObj.getDataBinding().getXpath(); } else { log.warn("couldn't find binding or bindingrole!"); // not all sdt's need have a binding; // they could be present in the docx for other purposes return; // NB an OpenDoPE xpath tag (with no w:binding element) // eg as created by authoring tool for a "count(" XPath // ends up here. } } else { thisXPath = binding.getXpath(); // Set this stuff up now bindingId = map.get(BINDING_ROLE_XPATH); xpathObj = XPathsPart.getXPathById(xPaths, bindingId); // Sanity test if (!thisXPath.equals(xpathObj.getDataBinding().getXpath())) { log.error( "XPaths didn't match for id " + bindingId + ": \n\r " + thisXPath + "\n\rcf. " + xpathObj.getDataBinding().getXpath()); } // 2012 09 20 - when did this break? // thisXPath = xpathObj.getDataBinding().getXpath(); } // System.out.println("xpathBase: " + xpathBase); // System.out.println("index: " + index); // System.out.println("thisXPath: " + thisXPath); final String newPath = enhanceXPath(xpathBase, index + 1, thisXPath); // System.out.println("newPath: " + newPath); if (log.isDebugEnabled() && !thisXPath.equals(newPath)) { log.debug("xpath prefix enhanced " + thisXPath + " to " + newPath); } if (binding == null) { if (repeatId != null) { // Create the new xpath object org.opendope.xpaths.Xpaths.Xpath newXPathObj = createNewXPathObject(newPath, xpathObj, index); // set sdt to use it map.put(BINDING_ROLE_REPEAT, newXPathObj.getId()); tag.setVal(QueryString.create(map)); } else if (map.containsKey(BINDING_CONTENTTYPE) || map.containsKey(BINDING_HANDLER) || map.containsKey(BINDING_PROGID)) { // Also need to create new xpath id, and add that org.opendope.xpaths.Xpaths.Xpath newXPathObj = createNewXPathObject(newPath, xpathObj, index); // set sdt to use it map.put(BINDING_ROLE_XPATH, newXPathObj.getId()); tag.setVal(QueryString.create(map)); } } else { binding.setXpath(newPath); // Also need to create new xpath id, and add that org.opendope.xpaths.Xpaths.Xpath newXPathObj = createNewXPathObject(newPath, xpathObj, index); // set sdt to use it map.put(BINDING_ROLE_XPATH, newXPathObj.getId()); tag.setVal(QueryString.create(map)); } }