def flatten(self, attr_ignore_predicate=None,force_nonleaf_fact_predicate=None,namespace_dict=None):
if not namespace_dict:<EOL><INDENT>namespace_dict = {}<EOL><DEDENT>def node_id_gen(n):<EOL><INDENT>"""<STR_LIT>"""<EOL>return "<STR_LIT>" % (n[<NUM_LIT:0>], n[<NUM_LIT:1>])<EOL><DEDENT>RE_ELEMENT_MATCHER = re.compile(r"<STR_LIT>")<EOL>def _flatten(self, result_list, attr_dict, elt_names, prefix):<EOL><INDENT>"""<STR_LIT>"""<EOL>if '<STR_LIT>' in self.keys():<EOL><INDENT>current_namespace = (namespace_dict.get(self.get('<STR_LIT>'),None),self.get('<STR_LIT>'))<EOL><DEDENT>else:<EOL><INDENT>current_namespace = (None,None)<EOL><DEDENT>attributes = filter(lambda x: x[<NUM_LIT:0>] == '<STR_LIT:@>', self.keys())<EOL>node_id = '<STR_LIT::>'.join(map(node_id_gen, prefix))<EOL>for attribute in attributes:<EOL><INDENT>if node_id not in attr_dict.keys():<EOL><INDENT>attr_dict[node_id] = {attribute[<NUM_LIT:1>:]: self[attribute]}<EOL><DEDENT>else:<EOL><INDENT>attr_dict[node_id][attribute[<NUM_LIT:1>:]] = self[attribute]<EOL><DEDENT><DEDENT>elements = filter(lambda x: RE_ELEMENT_MATCHER.match(x), self)<EOL>fact_data = {'<STR_LIT>': '<STR_LIT:/>'.join(elt_names),<EOL>'<STR_LIT>' : map(lambda x: x[<NUM_LIT:2>],prefix),<EOL>'<STR_LIT:value>': self.get('<STR_LIT>', '<STR_LIT>'),<EOL>'<STR_LIT>': False,<EOL>'<STR_LIT>': node_id}<EOL>if elements == [] or force_nonleaf_fact_predicate(fact_data,attributes):<EOL><INDENT>logger.debug("<STR_LIT>" % self)<EOL>if '<STR_LIT>' in self.keys() or attributes != []:<EOL><INDENT>fact_data = {'<STR_LIT>': '<STR_LIT:/>'.join(elt_names),<EOL>'<STR_LIT>' : map(lambda x: x[<NUM_LIT:2>],prefix),<EOL>'<STR_LIT:value>': self.get('<STR_LIT>', '<STR_LIT>'),<EOL>'<STR_LIT>': False,<EOL>'<STR_LIT>': node_id}<EOL>result_list.append(fact_data)<EOL>logger.debug("<STR_LIT>" % fact_data)<EOL><DEDENT><DEDENT>if elements != []:<EOL><INDENT>counter = <NUM_LIT:0><EOL>for element in elements:<EOL><INDENT>logger.debug("<STR_LIT>" % element)<EOL>if type(self[element]) == type([]):<EOL><INDENT>logger.debug("<STR_LIT>" % self[element])<EOL>for sub_elt in self[element]:<EOL><INDENT>current_namespace = (namespace_dict.get(sub_elt.get('<STR_LIT>'),None),sub_elt.get('<STR_LIT>'))<EOL>(result_list, attr_dict) = _flatten(sub_elt,<EOL>result_list=result_list,<EOL>attr_dict=attr_dict,<EOL>elt_names=elt_names + [element],<EOL>prefix=prefix + [('<STR_LIT:L>', counter,current_namespace)])<EOL>counter += <NUM_LIT:1><EOL><DEDENT><DEDENT>elif isinstance(self[element],basestring):<EOL><INDENT>logger.debug("<STR_LIT>" % self[element])<EOL>elt_names.append(element)<EOL>fact_data = {'<STR_LIT>': '<STR_LIT:/>'.join(elt_names),<EOL>'<STR_LIT>' : map(lambda x: x[<NUM_LIT:2>],prefix + [('<STR_LIT:N>',counter,current_namespace)]),<EOL>'<STR_LIT:value>': self[element],<EOL>'<STR_LIT>': False,<EOL>'<STR_LIT>': "<STR_LIT:%s>" % '<STR_LIT::>'.join(map(node_id_gen, prefix + [('<STR_LIT:N>', counter,current_namespace)]))}<EOL>logger.debug("<STR_LIT>" % fact_data)<EOL>result_list.append(fact_data)<EOL>elt_names = elt_names[:-<NUM_LIT:1>]<EOL>counter += <NUM_LIT:1><EOL><DEDENT>else:<EOL><INDENT>logger.debug("<STR_LIT>" % self[element])<EOL>current_namespace = (namespace_dict.get(self[element].get('<STR_LIT>'),None),self[element].get('<STR_LIT>'))<EOL>(result_list, attr_dict) = _flatten(self[element],<EOL>result_list=result_list,<EOL>attr_dict=attr_dict,<EOL>elt_names=elt_names + [element],<EOL>prefix=prefix + [('<STR_LIT:N>', counter,current_namespace)])<EOL>counter += <NUM_LIT:1><EOL><DEDENT><DEDENT><DEDENT>attr_counter = <NUM_LIT:0><EOL>for attribute in attributes:<EOL><INDENT>if node_id == '<STR_LIT>':<EOL><INDENT>attr_node_id = node_id_gen(('<STR_LIT:A>', attr_counter,(None,None)))<EOL><DEDENT>else:<EOL><INDENT>attr_node_id = "<STR_LIT>" % (node_id, node_id_gen(('<STR_LIT:A>', attr_counter,(None,None))))<EOL><DEDENT>fact = {'<STR_LIT>': "<STR_LIT:%s>" % ('<STR_LIT:/>'.join(elt_names)),<EOL>'<STR_LIT>' : map(lambda x: x[<NUM_LIT:2>],prefix),<EOL>'<STR_LIT:value>': self[attribute],<EOL>'<STR_LIT>': attr_node_id,<EOL>'<STR_LIT>': attribute[<NUM_LIT:1>:],<EOL>'<STR_LIT>': len(elements)}<EOL>if not attr_ignore_predicate(fact):<EOL><INDENT>del(fact['<STR_LIT>'])<EOL>result_list.append(fact)<EOL>logger.debug("<STR_LIT>" % fact)<EOL>attr_counter += <NUM_LIT:1><EOL><DEDENT>else:<EOL><INDENT>logger.debug("<STR_LIT>" % fact)<EOL><DEDENT><DEDENT>result_list.sort(key=lambda x: x['<STR_LIT>'])<EOL>return (result_list, attr_dict)<EOL><DEDENT>if not attr_ignore_predicate:<EOL><INDENT>attr_ignore_predicate = (lambda x: '<STR_LIT:@>' in x['<STR_LIT>'])<EOL><DEDENT>if not force_nonleaf_fact_predicate:<EOL><INDENT>force_nonleaf_fact_predicate = (lambda x,y: False)<EOL><DEDENT>return _flatten(self,result_list=[], attr_dict={}, elt_names=[], prefix=[])<EOL>
Flatten a Dingo dictionary representation of into a list
of fact-term/value pairs and associated information about tree structure (in node_id)
and a dictionary mapping XML attributes to node identifiers.

This all is best explained by example (see below).

Note that attributes are also represented in the flattened representation. There
are cases in which attributes should not lead to an entry in the flattened representation.
This can be configured by passing the flatten method a predicate function 'attr_ignore_predicate'.
The function takes a dictionary and returns True (ignore) or False (do not ignore). It
is passed the dictionary representing an entry in the flat representation, such as follows::

      { 'node_id': 'N001:L000:N000:A000',
      'term': 'Hashes/Hash/Simple_Hash_Value',
      'attribute': 'condition',
      'value': u'Equals'},

By default, the following predicate is used::

     (lambda x : '@' in x['attribute'])

This is because during import, DINGO adds certain annotations to the import dictionary
as attributes with a second leading '@'.

Input Example (CybOx)::

    {'File_Name': {'@condition': 'Equals',  '_value': u'UNITED NATIONS COMPENSATION SCHEME...pdf'},
      'Hashes': {'Hash': [{'Simple_Hash_Value':
                            {'@condition': 'Equals',
                             '@datatype': 'hexBinary',
                              '_value': u'576fea79dd23a352a14c3f8bf3dbc9eb732e1d54f804a29160894aec55df4bd5'},
                           'Type': {'_value': 'SHA256'}},
                          {'Simple_Hash_Value': {'@condition': 'Equals',
                                                 '@datatype': 'hexBinary',
                                                 '_value': u'491809c2092cecd633e43d465409a78c'},
                           'Type': {'_value': 'MD5'}}]
                }
    }

Output Example::

  [ { 'node_id': 'N000',
      'term': 'File_Name',
      'attribute': False,
      'value': u'UNITED NATIONS COMPENSATION SCHEME...pdf'},
      { 'node_id': 'N000:A000',
      'term': 'File_Name',
      'attribute': 'condition',
      'value': u'Equals'},
    { 'node_id': 'N001:L000:N000',
      'term': 'Hashes/Hash/Simple_Hash_Value',
      'attribute': False,
      'value': u'576fea79dd23a352a14c3f8bf3dbc9eb732e1d54f804a29160894aec55df4bd5'},
    { 'node_id': 'N001:L000:N000:A000',
      'term': 'Hashes/Hash/Simple_Hash_Value',
      'attribute': 'condition',
      'value': u'Equals'},
    { 'node_id': 'N001:L000:N000:A001',
      'term': 'Hashes/Hash/Simple_Hash_Value',
      'attribute': 'datatype',
      'value': u'hexBinary'},
    { 'node_id': 'N001:L000:N001',
      'term': 'Hashes/Hash/Type',
      'attribute': False,
      'value': 'SHA256'},
    { 'node_id': 'N001:L001:N000',
      'term': 'Hashes/Hash/Simple_Hash_Value',
      'attribute': False,
      'value': u'491809c2092cecd633e43d465409a78c'},
    { 'node_id': 'N001:L001:N000:A000',
      'term': 'Hashes/Hash/Simple_Hash_Value',
      'attribute': 'condition',
      'value': u'Equals'},
    { 'node_id': 'N001:L001:N000:A001',
      'term': 'Hashes/Hash/Simple_Hash_Value',
      'attribute': 'datatype',
      'value': u'hexBinary'},
    { 'node_id': 'N001:L001:N001',
      'term': 'Hashes/Hash/Type',
      'attribute': False,
      'value': 'MD5'}
  ]

  { 'N000': { 'condition': 'Equals'},
    'N001:L000:N000': { 'condition': 'Equals', 'datatype': 'hexBinary'},
    'N001:L001:N000': { 'condition': 'Equals', 'datatype': 'hexBinary'},
  }