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