docs: private void validateElement(List<ValidationMessage> errors, StructureDefinition profile, ElementDefinition definition, StructureDefinition cprofile, ElementDefinition context,
  			WrapperElement resource, WrapperElement element, String actualType, NodeStack stack, boolean inCodeableConcept) throws FHIRException {
  		element.setDefinition(definition);
  		element.setProfile(profile);
  
      // irrespective of what element it is, it cannot be empty
      if (element.isXml()) {
        rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), FormatUtilities.FHIR_NS.equals(element.getNamespace()),
            "Namespace mismatch - expected '" + FormatUtilities.FHIR_NS + "', found '" + element.getNamespace() + "'");
        rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), !element.hasNamespace("http://www.w3.org/2001/XMLSchema-instance"),
            "Schema Instance Namespace is not allowed in instances");
        rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), !element.hasProcessingInstruction(), "No Processing Instructions in resources");
      }
      rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), !empty(element), "Elements must have some content (@value, extensions, or children elements)");
  
  		checkInvariants(errors, stack.literalPath, profile, definition, null, null, resource, element);
  
      // get the list of direct defined children, including slices
      List<ElementDefinition> childDefinitions = ProfileUtilities.getChildMap(profile, definition.getName(), definition.getPath(), definition.getNameReference());
  
      // 1. List the children, and remember their exact path (convenience)
      List<ElementInfo> children = new ArrayList<InstanceValidator.ElementInfo>();
      ChildIterator iter = new ChildIterator(stack.getLiteralPath(), element);
      while (iter.next())
        children.add(new ElementInfo(iter.name(), iter.element(), iter.path(), iter.count()));
  
      // 2. assign children to a definition
      // for each definition, for each child, check whether it belongs in the slice
      ElementDefinition slice = null;
      for (ElementDefinition ed : childDefinitions) {
        boolean process = true;
        // where are we with slicing
        if (ed.hasSlicing()) {
          if (slice != null && slice.getPath().equals(ed.getPath()))
  					throw new DefinitionException("Slice encountered midway through path on " + slice.getPath());
          slice = ed;
          process = false;
        } else if (slice != null && !slice.getPath().equals(ed.getPath()))
          slice = null;
  
        if (process) {
          for (ElementInfo ei : children) {
            boolean match = false;
            if (slice == null) {
              match = nameMatches(ei.name, tail(ed.getPath()));
            } else {
              if (nameMatches(ei.name, tail(ed.getPath())))
                match = sliceMatches(ei.element, ei.path, slice, ed, profile);
            }
            if (match) {
              if (rule(errors, IssueType.INVALID, ei.line(), ei.col(), ei.path, ei.definition == null, "Element matches more than one slice"))
                ei.definition = ed;
            }
          }
        }
      }
      for (ElementInfo ei : children)
        if (ei.path.endsWith(".extension"))
          rule(errors, IssueType.INVALID, ei.line(), ei.col(), ei.path, ei.definition != null, "Element is unknown or does not match any slice (url=\"" + ei.element.getAttribute("url") + "\")");
        else
          rule(errors, IssueType.INVALID, ei.line(), ei.col(), ei.path, (ei.definition != null) || (!ei.element.isXml() && ei.element.getName().equals("fhir_comments")),
              "Element is unknown or does not match any slice");
  
      // 3. report any definitions that have a cardinality problem
      for (ElementDefinition ed : childDefinitions) {
        if (ed.getRepresentation().isEmpty()) { // ignore xml attributes
          int count = 0;
          for (ElementInfo ei : children)
            if (ei.definition == ed)
              count++;
          if (ed.getMin() > 0) {
            rule(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), count >= ed.getMin(),
                "Element '" + stack.getLiteralPath() + "." + tail(ed.getPath()) + "': minimum required = " + Integer.toString(ed.getMin()) + ", but only found " + Integer.toString(count));
          }
          if (ed.hasMax() && !ed.getMax().equals("*")) {
            rule(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), count <= Integer.parseInt(ed.getMax()),
                "Element " + tail(ed.getPath()) + " @ " + stack.getLiteralPath() + ": max allowed = " + ed.getMax() + ", but found " + Integer.toString(count));
          }
  
        }
      }
      // 4. check order if any slices are orderd. (todo)
  
      // 5. inspect each child for validity
      for (ElementInfo ei : children) {
        if (ei.definition != null) {
          String type = null;
          ElementDefinition typeDefn = null;
          if (ei.definition.getType().size() == 1 && !ei.definition.getType().get(0).getCode().equals("*") && !ei.definition.getType().get(0).getCode().equals("Element")
              && !ei.definition.getType().get(0).getCode().equals("BackboneElement"))
            type = ei.definition.getType().get(0).getCode();
          else if (ei.definition.getType().size() == 1 && ei.definition.getType().get(0).getCode().equals("*")) {
            String prefix = tail(ei.definition.getPath());
            assert prefix.endsWith("[x]");
            type = ei.name.substring(prefix.length() - 3);
            if (isPrimitiveType(type))
              type = Utilities.uncapitalize(type);
          } else if (ei.definition.getType().size() > 1) {
  
            String prefix = tail(ei.definition.getPath());
            assert typesAreAllReference(ei.definition.getType()) || prefix.endsWith("[x]") : prefix;
  
            prefix = prefix.substring(0, prefix.length() - 3);
            for (TypeRefComponent t : ei.definition.getType())
              if ((prefix + Utilities.capitalize(t.getCode())).equals(ei.name))
                type = t.getCode();
            if (type == null) {
              TypeRefComponent trc = ei.definition.getType().get(0);
              if (trc.getCode().equals("Reference"))
                type = "Reference";
              else 
                rule(errors, IssueType.STRUCTURE, ei.line(), ei.col(), stack.getLiteralPath(), false,
                    "The element " + ei.name + " is illegal. Valid types at this point are " + describeTypes(ei.definition.getType()));
            }
          } else if (ei.definition.getNameReference() != null) {
            typeDefn = resolveNameReference(profile.getSnapshot(), ei.definition.getNameReference());
          }
  
          if (type != null) {
            if (type.startsWith("@")) {
              ei.definition = findElement(profile, type.substring(1));
              type = null;
            }
          }
          NodeStack localStack = stack.push(ei.element, ei.count, ei.definition, type == null ? typeDefn : resolveType(type));
          String localStackLiterapPath = localStack.getLiteralPath();
          String eiPath = ei.path;
          assert(eiPath.equals(localStackLiterapPath)) : "ei.path: " + ei.path + "  -  localStack.getLiterapPath: " + localStackLiterapPath;
          boolean thisIsCodeableConcept = false;
  
          if (type != null) {
            if (isPrimitiveType(type))
              checkPrimitive(errors, ei.path, type, ei.definition, ei.element);
            else {
              if (type.equals("Identifier"))
                checkIdentifier(errors, ei.path, ei.element, ei.definition);
              else if (type.equals("Coding"))
                checkCoding(errors, ei.path, ei.element, profile, ei.definition, inCodeableConcept);
              else if (type.equals("CodeableConcept")) {
                checkCodeableConcept(errors, ei.path, ei.element, profile, ei.definition);
                thisIsCodeableConcept = true;
              } else if (type.equals("Reference"))
                checkReference(errors, ei.path, ei.element, profile, ei.definition, actualType, localStack);
              
              if (type.equals("Extension"))
                checkExtension(errors, ei.path, ei.element, ei.definition, profile, localStack);
              else if (type.equals("Resource"))
  							validateContains(errors, ei.path, ei.definition, definition, resource, ei.element, localStack, idStatusForEntry(element, ei)); // if
              // (str.matches(".*([.,/])work\\1$"))
              else {
                StructureDefinition p = getProfileForType(type);
                if (rule(errors, IssueType.STRUCTURE, ei.line(), ei.col(), ei.path, p != null, "Unknown type " + type)) {
  								validateElement(errors, p, p.getSnapshot().getElement().get(0), profile, ei.definition, resource, ei.element, type, localStack, thisIsCodeableConcept);
                }
              }
            }
          } else {
            if (rule(errors, IssueType.STRUCTURE, ei.line(), ei.col(), stack.getLiteralPath(), ei.definition != null, "Unrecognised Content " + ei.name))
  						validateElement(errors, profile, ei.definition, null, null, resource, ei.element, type, localStack, false);
  				}
  			}
  		}
  	}