Skip to content

Provide method for getting namespace from any ID #176

Description

@bworrell

STIX IDs are QNames, which contain namespaces as part of their form. We should provide either a utility method or a new class for IDs that has a method for returning the namespace along with the id itself.

Activity

  1. bworrell commented on Aug 19, 2014

    @bworrell
    ContributorAuthor

    Something like...

    stix_package.id_.get_namespace() # returns {'namespace': 'http://example.com', 'alias': 'example'}
    
    # OR
    
    stix.utils.get_id_namespace(stix_package.id_)  # returns {'namespace': 'http://example.com', 'alias': 'example'}
  2. usrlocalben commented on Aug 31, 2014

    @usrlocalben
    Contributor

    Here's my hack for id/idref namespaces... read-only, diff only includes Indicator.

    diff --git a/stix/bindings/stix_common.py b/stix/bindings/stix_common.py
    index f550507..069ed79 100644
    --- a/stix/bindings/stix_common.py
    +++ b/stix/bindings/stix_common.py
    @@ -342,6 +342,31 @@ def find_attr_value_(attr_name, node):
                 value = attrs.get('{%s}%s' % (namespace, name, ))
         return value
    
    +def find_attr_value_qname(attr_name, node):
    +    attrs = node.attrib
    +    attr_parts = attr_name.split(':')
    +    value = None
    +    if len(attr_parts) == 1:
    +        value = attrs.get(attr_name)
    +    elif len(attr_parts) == 2:
    +        prefix, name = attr_parts
    +        namespace = node.nsmap.get(prefix)
    +        if namespace is not None:
    +            value = attrs.get('{%s}%s' % (namespace, name, ))
    +    if value is None:
    +        return None, None
    +    val_parts = value.split(':')
    +    if len(val_parts) == 1:
    +        return value, None
    +    elif len(val_parts) == 2:
    +        prefix, data = val_parts
    +        namespace = node.nsmap.get(prefix)
    +        if namespace is not None:
    +            return value, namespace
    +        else:
    +            raise ValueError("No namespace defined for qname prefix %s" % (prefix))
    +    else:
    +        raise ValueError("Malformed qname %s" % (value))
    
     class GDSParseError(Exception):
         pass
    @@ -2617,9 +2642,11 @@ class IndicatorBaseType(GeneratedsSuper):
         specified elsewhere."""
         subclass = None
         superclass = None
    -    def __init__(self, idref=None, id=None, timestamp=None):
    +    def __init__(self, idref=None, id=None, timestamp=None, idrefns=None, idns=None):
             self.idref = _cast(None, idref)
    +        self.idrefns = _cast(None, idrefns)
             self.id = _cast(None, id)
    +        self.idns = _cast(None, idns)
             self.timestamp = _cast(None, timestamp)
         def factory(*args_, **kwargs_):
             if IndicatorBaseType.subclass:
    @@ -2627,9 +2654,9 @@ class IndicatorBaseType(GeneratedsSuper):
             else:
                 return IndicatorBaseType(*args_, **kwargs_)
         factory = staticmethod(factory)
    -    def get_idref(self): return self.idref
    +    def get_idref(self): return self.idref, self.idrefns
         def set_idref(self, idref): self.idref = idref
    -    def get_id(self): return self.id
    +    def get_id(self): return self.id, self.idns
         def set_id(self, id): self.id = id
         def get_timestamp(self): return self.timestamp
         def set_timestamp(self, timestamp): self.timestamp = timestamp
    @@ -2674,14 +2701,16 @@ class IndicatorBaseType(GeneratedsSuper):
                 nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
                 self.buildChildren(child, node, nodeName_)
         def buildAttributes(self, node, attrs, already_processed):
    -        value = find_attr_value_('idref', node)
    +        value, ns = find_attr_value_qname('idref', node)
             if value is not None and 'idref' not in already_processed:
                 already_processed.add('idref')
                 self.idref = value
    -        value = find_attr_value_('id', node)
    +            self.idrefns = ns
    +        value, ns = find_attr_value_qname('id', node)
             if value is not None and 'id' not in already_processed:
                 already_processed.add('id')
                 self.id = value
    +            self.idns = ns
             value = find_attr_value_('timestamp', node)
             if value is not None and 'timestamp' not in already_processed:
                 already_processed.add('timestamp')
    diff --git a/stix/indicator/indicator.py b/stix/indicator/indicator.py
    index f3ab87f..517a50f 100644
    --- a/stix/indicator/indicator.py
    +++ b/stix/indicator/indicator.py
    @@ -513,8 +513,8 @@ class Indicator(stix.Entity):
             if not return_obj:
                 return_obj = cls()
    
    -        return_obj.id_              = obj.get_id()
    -        return_obj.idref            = obj.get_idref()
    +        return_obj.id_,return_obj.id_ns = obj.get_id()
    +        return_obj.idref,return_obj.idref_ns = obj.get_idref()
             return_obj.timestamp        = obj.get_timestamp()
    
             if isinstance(obj, cls._binding_class):
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions