def test_nsinfo_collect(self): """Tests that the NamespaceInfo.collect() method correctly ascends the MRO of input objects. """ nsinfo = NamespaceCollector() # Collect classes nsinfo.collect(C()) # Parse collected classes nsinfo._parse_collected_classes() self.assertEqual(len(nsinfo._collected_namespaces), 3) # noqa
def test_namespace_collect(self): """Test that NamespaceInfo correctly pulls namespaces from all classes in an objects MRO. """ nsinfo = NamespaceCollector() # Collect classes nsinfo.collect(C()) # finalize the namespace dictionary nsinfo.finalize(ns_dict=NSMAP, schemaloc_dict=SCHEMALOCS) namespaces = nsinfo.binding_namespaces.keys() self.assertTrue(all(ns in namespaces for ns in six.iterkeys(NSMAP)))
def to_xml(self, include_namespaces=True, include_schemalocs=False, ns_dict=None, schemaloc_dict=None, pretty=True, auto_namespace=True, encoding='utf-8'): """Serializes a :class:`Entity` instance to an XML string. The default character encoding is ``utf-8`` and can be set via the `encoding` parameter. If `encoding` is ``None``, a string (unicode in Python 2, str in Python 3) is returned. Args: auto_namespace: Automatically discover and export XML namespaces for a STIX :class:`Entity` instance. include_namespaces: Export namespace definitions in the output XML. Default is ``True``. include_schemalocs: Export ``xsi:schemaLocation`` attribute in the output document. This will attempt to associate namespaces declared in the STIX document with schema locations. If a namespace cannot be resolved to a schemaLocation, a Python warning will be raised. Schemalocations will only be exported if `include_namespaces` is also ``True``. ns_dict: Dictionary of XML definitions (namespace is key, alias is value) to include in the exported document. This must be passed in if `auto_namespace` is ``False``. schemaloc_dict: Dictionary of XML ``namespace: schema location`` mappings to include in the exported document. These will only be included if `auto_namespace` is ``False``. pretty: Pretty-print the XML. encoding: The output character encoding. Default is ``utf-8``. If `encoding` is set to ``None``, a string (unicode in Python 2, str in Python 3) is returned. Returns: An XML string for this :class:`Entity` instance. Default character encoding is ``utf-8``. """ from mixbox.entities import NamespaceCollector if (not auto_namespace) and (not ns_dict): raise Exception( "Auto-namespacing was disabled but ns_dict was empty " "or missing.") ns_info = NamespaceCollector() obj = self.to_obj(ns_info=ns_info if auto_namespace else None) ns_info.finalize(ns_dict=ns_dict, schemaloc_dict=schemaloc_dict) if auto_namespace: obj_ns_dict = ns_info.binding_namespaces else: obj_ns_dict = dict( itertools.chain(iteritems(ns_info.binding_namespaces), iteritems(namespaces.get_full_ns_map()))) namespace_def = "" if include_namespaces: delim = "\n\t" if pretty else " " xmlns = ns_info.get_xmlns_string(delim) namespace_def += (delim + xmlns) if include_schemalocs: schemaloc = ns_info.get_schema_location_string(delim) namespace_def += (delim + schemaloc) with binding_utils.save_encoding(encoding): sio = StringIO() obj.export( sio.write, # output buffer 0, # output level obj_ns_dict, # namespace dictionary pretty_print=pretty, # pretty printing namespacedef_=namespace_def # namespace/schemaloc def string ) # Ensure that the StringIO buffer is unicode s = text_type(sio.getvalue()) if encoding: return s.encode(encoding) return s
def round_trip(o, output=False, list_=False): """ Performs all eight conversions to verify import/export functionality. 1. cybox.Entity -> dict/list 2. dict/list -> JSON string 3. JSON string -> dict/list 4. dict/list -> cybox.Entity 5. cybox.Entity -> Bindings Object 6. Bindings Object -> XML String 7. XML String -> Bindings Object 8. Bindings object -> cybox.Entity It returns the final object, so tests which call this function can check to ensure it was not modified during any of the transforms. """ klass = o.__class__ if output: print("Class: ", klass) print("-" * 40) # 1. cybox.Entity -> dict/list if list_: d = o.to_list() else: d = o.to_dict() # 2. dict/list -> JSON string json_string = json.dumps(d) if output: print(json_string) print("-" * 40) # Before parsing the JSON, make sure the cache is clear cybox.utils.cache_clear() # 3. JSON string -> dict/list d2 = json.loads(json_string) # 4. dict/list -> cybox.Entity if list_: o2 = klass.from_list(d2) else: o2 = klass.from_dict(d2) # 5. Entity -> Bindings Object ns_info = NamespaceCollector() xobj = o2.to_obj(ns_info=ns_info) try: # 6. Bindings Object -> XML String xml_string = o2.to_xml(encoding=ExternalEncoding) if not isinstance(xml_string, text_type): xml_string = xml_string.decode(ExternalEncoding) except KeyError as ex: print(str(ex)) ns_info.finalize() print(ns_info.binding_namespaces) raise ex if output: print(xml_string) print("-" * 40) # Before parsing the XML, make sure the cache is clear cybox.utils.cache_clear() # 7. XML String -> Bindings Object xobj2 = klass._binding.parseString(xml_string) # 8. Bindings object -> cybox.Entity o3 = klass.from_obj(xobj2) return o3