docs: public ScopeImpl parseMultiInstanceLoopCharacteristics(Element activityElement, ScopeImpl scope) {
  
      Element miLoopCharacteristics = activityElement.element("multiInstanceLoopCharacteristics");
      if (miLoopCharacteristics == null) {
        return null;
      } else {
        String id = activityElement.attribute("id");
  
        LOG.parsingElement("mi body for activity", id);
  
        id = getIdForMiBody(id);
        ActivityImpl miBodyScope = scope.createActivity(id);
        setActivityAsyncDelegates(miBodyScope);
        miBodyScope.setProperty(PROPERTYNAME_TYPE, ActivityTypes.MULTI_INSTANCE_BODY);
        miBodyScope.setScope(true);
  
        boolean isSequential = parseBooleanAttribute(miLoopCharacteristics.attribute("isSequential"), false);
  
        MultiInstanceActivityBehavior behavior = null;
        if (isSequential) {
          behavior = new SequentialMultiInstanceActivityBehavior();
        } else {
          behavior = new ParallelMultiInstanceActivityBehavior();
        }
        miBodyScope.setActivityBehavior(behavior);
  
        // loopCardinality
        Element loopCardinality = miLoopCharacteristics.element("loopCardinality");
        if (loopCardinality != null) {
          String loopCardinalityText = loopCardinality.getText();
          if (loopCardinalityText == null || "".equals(loopCardinalityText)) {
            addError("loopCardinality must be defined for a multiInstanceLoopCharacteristics definition ", miLoopCharacteristics);
          }
          behavior.setLoopCardinalityExpression(expressionManager.createExpression(loopCardinalityText));
        }
  
        // completionCondition
        Element completionCondition = miLoopCharacteristics.element("completionCondition");
        if (completionCondition != null) {
          String completionConditionText = completionCondition.getText();
          behavior.setCompletionConditionExpression(expressionManager.createExpression(completionConditionText));
        }
  
        // activiti:collection
        String collection = miLoopCharacteristics.attributeNS(CAMUNDA_BPMN_EXTENSIONS_NS, "collection");
        if (collection != null) {
          if (collection.contains("{")) {
            behavior.setCollectionExpression(expressionManager.createExpression(collection));
          } else {
            behavior.setCollectionVariable(collection);
          }
        }
  
        // loopDataInputRef
        Element loopDataInputRef = miLoopCharacteristics.element("loopDataInputRef");
        if (loopDataInputRef != null) {
          String loopDataInputRefText = loopDataInputRef.getText();
          if (loopDataInputRefText != null) {
            if (loopDataInputRefText.contains("{")) {
              behavior.setCollectionExpression(expressionManager.createExpression(loopDataInputRefText));
            } else {
              behavior.setCollectionVariable(loopDataInputRefText);
            }
          }
        }
  
        // activiti:elementVariable
        String elementVariable = miLoopCharacteristics.attributeNS(CAMUNDA_BPMN_EXTENSIONS_NS, "elementVariable");
        if (elementVariable != null) {
          behavior.setCollectionElementVariable(elementVariable);
        }
  
        // dataInputItem
        Element inputDataItem = miLoopCharacteristics.element("inputDataItem");
        if (inputDataItem != null) {
          String inputDataItemName = inputDataItem.attribute("name");
          behavior.setCollectionElementVariable(inputDataItemName);
        }
  
        // Validation
        if (behavior.getLoopCardinalityExpression() == null && behavior.getCollectionExpression() == null && behavior.getCollectionVariable() == null) {
          addError("Either loopCardinality or loopDataInputRef/activiti:collection must been set", miLoopCharacteristics);
        }
  
        // Validation
        if (behavior.getCollectionExpression() == null && behavior.getCollectionVariable() == null && behavior.getCollectionElementVariable() != null) {
          addError("LoopDataInputRef/activiti:collection must be set when using inputDataItem or activiti:elementVariable", miLoopCharacteristics);
        }
  
        for (BpmnParseListener parseListener : parseListeners) {
          parseListener.parseMultiInstanceLoopCharacteristics(activityElement, miLoopCharacteristics, miBodyScope);
        }
  
        return miBodyScope;
      }
    }