private void processDescendantCondition(Object sdt, String xpathBase, int index, Tag tag) {

    Condition c = null;

    HashMap<String, String> map = QueryString.parseQueryString(tag.getVal(), true);

    String conditionId = map.get(BINDING_ROLE_CONDITIONAL);

    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));

      Condition newCondition = c.repeat(xpathBase, index, conditions, xPaths);

      // set sdt to use it
      map.put(BINDING_ROLE_CONDITIONAL, newCondition.getId());
      tag.setVal(QueryString.create(map));
    }
  }
    @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());
          }
        }
      }
    }
  /**
   * This applies to any sdt which might be a conditional|repeat
   *
   * @param wordMLPackage
   * @param sdtParent
   * @param sdt
   * @param tag
   * @param sdtContent
   * @return
   * @throws Exception
   */
  private List<Object> processBindingRoleIfAny(WordprocessingMLPackage wordMLPackage, Object sdt) {
    log.debug("Processing " + getSdtPr(sdt).getId().getVal());
    Tag tag = getSdtPr(sdt).getTag();

    if (tag == null) {
      List<Object> newContent = new ArrayList<Object>();
      newContent.add(sdt);
      return newContent;
    }

    log.info(tag.getVal());

    HashMap<String, String> map = QueryString.parseQueryString(tag.getVal(), true);

    String conditionId = map.get(BINDING_ROLE_CONDITIONAL);
    String repeatId = map.get(BINDING_ROLE_REPEAT);
    String xp = map.get(BINDING_ROLE_XPATH);
    if (conditionId == null && repeatId == null && xp == null) {
      List<Object> newContent = new ArrayList<Object>();
      newContent.add(sdt);
      return newContent;
    }

    Map<String, CustomXmlPart> customXmlDataStorageParts =
        wordMLPackage.getCustomXmlDataStorageParts();

    if (conditionId != null) {

      log.info("Processing Conditional: " + tag.getVal());

      // At present, this only handles simple conditions
      Condition c = ConditionsPart.getConditionById(conditions, conditionId);
      if (c == null) {
        log.error("Missing condition " + conditionId);
      }

      if (c.evaluate(wordMLPackage, customXmlDataStorageParts, conditions, xPaths)) {
        log.debug("so keeping");

        List<Object> newContent = new ArrayList<Object>();
        newContent.add(sdt);
        return newContent;

      } else {
        return conditionFalse(sdt);
      }

    } else if (repeatId != null) {

      log.info("Processing Repeat: " + tag.getVal());

      return processRepeat(
          sdt, customXmlDataStorageParts, wordMLPackage.getMainDocumentPart().getXPathsPart());

    } else if (xp != null) {

      // Word can't handle an XPath that returns something
      // other than an element
      // eg string or boolean or number, so we'll need to work this out.
      // In principal, we could do this in this pre-processing step,
      // or via bind.xslt.

      // Doing it here means the bind.xslt step can be restricted to pure
      // Word-like processing.

      // Doing it there means we can take advantage of the multiline
      // processing we have there, and less code.
      // So as from 13 Sept 2011 (what will be 2.7.1), do it there.

      List<Object> newContent = new ArrayList<Object>();
      newContent.add(sdt);
      return newContent;
    }
    // shouldn't happen
    return null;
  }