docs: def stix_embedding_pred(self, parent, child, ns_mapping):
          """
          Predicate for recognizing inlined content in an XML; to
          be used for DINGO's xml-import hook 'embedded_predicate'.
          The question this predicate must answer is whether
          the child should be extracted into a separate object.
  
          The function returns either
          - False (the child is not to be extracted)
          - True (the child is extracted but nothing can be inferred
            about what kind of object is extracted)
          - a string giving some indication about the object type
            (if nothing else is known: the name of the element, often the
             namespace of the embedded object)
          - a dictionary, of the following form::
  
               {'id_and_revision_info' : { 'id': something/None,
                                           'ts': something/None,
                                            ... other information you want to
                                            record for this object for later usage,
                                         },
                'embedded_ns': False/True/some indication about object type as string}
  
          Note: the 'parent' and 'child' arguments are XMLNodes as defined
          by the Python libxml2 bindings. If you have never worked with these, have a look at
  
          - Mike Kneller's brief intro: http://mikekneller.com/kb/python/libxml2python/part1
          - the functions in django-dingos core.xml_utils module
          """
  
          def extract_typeinfo(child):
              """
              When recognizing an embedding object, we try to find out what
              kind of object it is
              """
  
              # Let's try to find a grandchild and return the namespace of this grandchild:
              # This can be used as indicator for the object type that is referenced here.
  
              # Let's further try to find a grandchild (if there is one)
  
              grandchild = child.children
              type_info = None
  
              while grandchild is not None:
                  try:
                      grandchild_attrs = extract_attributes(grandchild, prefix_key_char='')
                      if 'xsi:type' in grandchild_attrs and grandchild.name=='Properties':
                          type_info = grandchild_attrs['xsi:type'].split(':')[0]
                      else:
                          type_info = grandchild.ns().name
                      break
  
                  except:
                      # This catches if the grandchild does not have a namespace
                      grandchild = grandchild.next
              if type_info:
                  logger.debug("Found type info %s" % type_info)
                  return type_info
              else:
                  logger.debug("Embedding, but did not find type info")
                  return True
  
          child_attributes = extract_attributes(child, prefix_key_char='')
  
          parent_attrs = extract_attributes(parent, prefix_key_char='')
  
  
          # We start with some special cases. If we find
          # OpenIOC content in a test mechanism, we use the embedded-predicate
          # to pass along additional information: by setting the key 'defer_processing'
          # in the 'id_and_revision_info', we tell the DINGOS xml_importer to
          # return the child element unprocessed.
  
          if parent.name=='Test_Mechanism':
              if 'xsi:type' in parent_attrs:
                  if 'OpenIOC2010TestMechanismType' in parent_attrs['xsi:type']:
                      # We have an embedded OpenIOC document.
  
                      # We extract id and revision info and tag it for deferred treatement
                      id_and_revision_info = OpenIOC_Importer.id_and_revision_extractor(child)
                      id_and_revision_info['defer_processing'] = {'processor': 'OpenIOC2010'}
                      logger.debug("XXX: Found OpenIOC with %s" % id_and_revision_info)
                      return {'embedded_ns':child.ns().name,
                              'id_and_revision_info':id_and_revision_info}
  
  
  
          if parent.name=='Kill_Chain' and child.name=='Kill_Chain_Phase':
              # We also extract kill-chain phases. Not sure whether that
              # is the best idea, though.
              logger.debug("Found killchain phase %s" % extract_typeinfo(child))
              return extract_typeinfo(child)
  
  
          if parent.name=='Handling' and child.name=='Marking' and parent.get_parent().name =='STIX_Header':
  
              # We also cut out Markings, because we need an InfoObject with the Marking
              # contents in order to create markings for the import.
              # We seed the id_and_revision info for this object with a tag 'import_first',
              # which will be read later below in the xml_import function: marking objects
              # will be imported first and a marking dictionary will provide information on
              # which STIX Package provided which marking.
  
              # Markings do not carry identifiers. The xml_importer will automagically create
              # an identifier derived from the identifier of the encompassing object.
  
              return {'embedded_ns': extract_typeinfo(child),
                      'id_and_revision_info' : {'import_first': True}}
  
          # Finally, the standard case: an 'id' attribute signifies
          # an embedded object that we want to extract.
          if ('id' in child_attributes):
              return extract_typeinfo(child)
  
          # 'object_reference' is used in Cybox as follows::
          #
          #     (...)
          #     <EmailMessageObj:Attachments>
          #           <EmailMessageObj:File xsi:type="FileObj:FileObjectType"
          #              object_reference="cybox:object-3cf6a958-5c3f-11e2-a06c-0050569761d3"/>
          #     </EmailMessageObj:Attachments>
          #     (...)
          #
          # That is actually a reference, but we need to turn it into an '@idref'-reference.
          # By treating the 'File' object-reference as an embedded object, this is done
          # automatically, because the xml_importer replaces embedded content with
          # '@idref'-based references.
  
          if 'object_reference' in child_attributes:
              return extract_typeinfo(child)
  
          if child.name=='Object' and not 'idref' in child_attributes:
              # Unfortunately, e.g., the example files created by MITRE from Mandiant reports
              # and OpenIOCs give an identifier to an observable, but not to the
              # object embedded in the observable. We, however, need an identifier for
              # the object, because otherwise the whole machinery that infers an object's
              # type does not work. So, if we find an object without identifier that
              # is embedded in an observable with identifier, we also want to extract
              # the object ... and need to derive the object identifier from the
              # observable identifier. This is done automagically by the xml_import
              # function itself.
  
              return extract_typeinfo(child)
          return False