Ejemplo n.º 1
0
    def addXMLNSDeclaration(self, element, namespace, prefix=None):
        """Manually add an XMLNS declaration to the document element.

        @param namespace: a L{pyxb.namespace.Namespace} instance

        @param prefix: the prefix by which the namespace is known.  If
        C{None}, the default prefix as previously declared will be used; if
        C{''} (empty string) a declaration for C{namespace} as the default
        namespace will be generated.

        @return: C{prefix} as used in the added declaration.
        """
        if not isinstance(namespace, pyxb.namespace.Namespace):
            raise pyxb.UsageError(
                'addXMLNSdeclaration: must be given a namespace instance')
        if namespace.isAbsentNamespace():
            raise pyxb.UsageError(
                'addXMLNSdeclaration: namespace must not be an absent namespace'
            )
        if prefix is None:
            prefix = self.namespacePrefix(namespace)
        if not prefix:  # None or empty string
            an = 'xmlns'
        else:
            an = 'xmlns:' + prefix
        element.setAttributeNS(pyxb.namespace.XMLNamespaces.uri(), an,
                               namespace.uri())
        return prefix
Ejemplo n.º 2
0
    def __new__ (cls, *args, **kw):
        """Pickling and singleton support.

        This ensures that no more than one Namespace instance exists
        for any given URI.  We could do this up in __init__, but that
        doesn't normally get called when unpickling instances; this
        does.  See also __getnewargs__()."""
        (uri,) = args
        if isinstance(uri, tuple):
            # Special handling to reconstruct absent namespaces.
            (variant, uid) = uri
            if cls.__SerializedVariantAbsent == variant:
                ns = cls.__AbsentNamespaceRegistry.get(uid)
                if ns is None:
                    raise pyxb.UsageError('Unable to reconstruct instance of absent namespace')
                return ns
            raise pyxb.LogicError('Unrecognized serialized namespace variant %s uid %s' % (variant, uid))
        elif not (uri in cls.__Registry):
            instance = object.__new__(cls)
            # Do this one step of __init__ so we can do checks during unpickling
            instance.__uri = uri
            instance._reset()
            # Absent namespaces are not stored in the registry.
            if uri is None:
                cls.__AbsentNamespaces.add(instance)
                return instance
            cls.__Registry[uri] = instance
        return cls.__Registry[uri]
Ejemplo n.º 3
0
    def _NamespaceForURI (cls, uri):
        """If a Namespace instance for the given URI exists, return it; otherwise return None.

        Note: Absent namespaces are not stored in the registry.  If you use
        one (e.g., for a schema with no target namespace), don't lose hold of
        it."""
        if uri is None:
            raise pyxb.UsageError('Absent namespaces are unlocatable')
        return cls.__Registry.get(uri)
Ejemplo n.º 4
0
    def declareNamespace(self, namespace, prefix=None, add_to_map=False):
        """Record the given namespace as one to be used in this document.

        @param namespace: The namespace to be associated with the document.
        @type namespace: L{pyxb.namespace.Namespace}

        @keyword prefix: Optional prefix to be used with this namespace.  If
        not provided, a unique prefix is generated or a standard prefix is
        used, depending on the namespace.

        @return: a prefix that may be used with the namespace.  If C{prefix}
        was C{None} the return value may be a previously-assigned prefix.

        @todo: ensure multiple namespaces do not share the same prefix
        @todo: provide default prefix in L{pyxb.namespace.Namespace}
        """
        if not isinstance(namespace, pyxb.namespace.Namespace):
            raise pyxb.UsageError(
                'declareNamespace: must be given a namespace instance')
        if namespace.isAbsentNamespace():
            raise pyxb.UsageError(
                'declareNamespace: namespace must not be an absent namespace')
        if prefix is None:
            prefix = namespace.prefix()
        if prefix is None:
            pfxs = self.__inScopePrefixes.get(namespace)
            if pfxs:
                prefix = next(iter(pfxs))
        while prefix is None:
            self.__namespacePrefixCounter += 1
            candidate_prefix = 'ns%d' % (self.__namespacePrefixCounter, )
            if not (candidate_prefix in self.__inScopeNamespaces):
                prefix = candidate_prefix
        ns = self.__inScopePrefixes.get(prefix)
        if ns:
            if ns != namespace:
                raise pyxb.LogicError('Prefix %s is already in use for %s' %
                                      (prefix, ns))
            return prefix
        if not self.__mutableInScopeNamespaces:
            self.__clonePrefixMap()
            self.__mutableInScopeNamespaces = True
        self.__addPrefixMap(prefix, namespace)
        return prefix
Ejemplo n.º 5
0
    def declareNamespace(self, namespace, prefix=None, add_to_map=False):
        """Add the given namespace as one to be used in this document.

        @param namespace: The namespace to be associated with the document.
        @type namespace: L{pyxb.namespace.Namespace}

        @keyword prefix: Optional prefix to be used with this namespace.  If
        not provided, a unique prefix is generated or a standard prefix is
        used, depending on the namespace.

        @keyword add_to_map: If C{False} (default), the prefix is not added to
        the namespace prefix map.  If C{True} it is added.  (Often, things
        added to the prefix map are preserved across resets, which is often
        not desired for specific prefix/namespace pairs).

        @todo: ensure multiple namespaces do not share the same prefix
        @todo: provide default prefix in L{pyxb.namespace.Namespace}
        @todo: support multiple prefixes for each namespace
        """
        if not isinstance(namespace, pyxb.namespace.Namespace):
            raise pyxb.UsageError(
                'declareNamespace: must be given a namespace instance')
        if namespace.isAbsentNamespace():
            raise pyxb.UsageError(
                'declareNamespace: namespace must not be an absent namespace')
        if prefix is None:
            prefix = self.__namespaces.get(namespace)
        if prefix is None:
            prefix = self.__namespacePrefixMap.get(namespace)
        if prefix is None:
            prefix = namespace.prefix()
        if prefix is None:
            self.__namespacePrefixCounter += 1
            prefix = 'ns%d' % (self.__namespacePrefixCounter, )
        if prefix == self.__namespaces.get(namespace):
            return prefix
        if prefix in self.__prefixes:
            raise pyxb.LogicError('Prefix %s is already in use' % (prefix, ))
        self.__namespaces[namespace] = prefix
        self.__prefixes.add(prefix)
        if add_to_map:
            self.__namespacePrefixMap[namespace] = prefix
        return prefix
Ejemplo n.º 6
0
 def setPrefix(self, prefix):
     if self.__boundPrefix is not None:
         if self.__boundPrefix == prefix:
             return self
         raise pyxb.NamespaceError(
             self, 'Cannot change the prefix of a bound namespace')
     if (None is not prefix) and (0 == len(prefix)):
         raise pyxb.UsageError('prefix must be non-empty string')
     self.__prefix = prefix
     return self
Ejemplo n.º 7
0
    def _makeURINodeNamePair(self, node):
        """Convert namespace information from a DOM node to text for new DOM node.

        The namespaceURI and nodeName are extracted and parsed.  The namespace
        (if any) is registered within the document, along with any prefix from
        the node name.  A pair is returned where the first element is the
        namespace URI or C{None}, and the second is a QName to be used for the
        expanded name within this document.

        @param node: An xml.dom.Node instance, presumably from a wildcard match.
        @rtype: C{( str, str )}"""
        ns = None
        if node.namespaceURI is not None:
            ns = pyxb.namespace.NamespaceForURI(node.namespaceURI,
                                                create_if_missing=True)
        if node.ELEMENT_NODE == node.nodeType:
            name = node.tagName
        elif node.ATTRIBUTE_NODE == node.nodeType:
            name = node.name
            # saxdom uses the uriTuple as the name field while minidom uses
            # the QName.  @todo saxdom should be fixed.
            if isinstance(name, tuple):
                name = name[1]
        else:
            raise pyxb.UsageError('Unable to determine name from DOM node %s' %
                                  (node, ))
        pfx = None
        local_name = name
        if 0 < name.find(':'):
            (pfx, local_name) = name.split(':', 1)
            if ns is None:
                raise pyxb.LogicError(
                    'QName with prefix but no available namespace')
        ns_uri = None
        node_name = local_name
        if ns is not None:
            ns_uri = ns.uri()
            self.declareNamespace(ns, pfx)
            if pfx is None:
                pfx = self.namespacePrefix(ns)
            if pfx is not None:
                node_name = '%s:%s' % (pfx, local_name)
        return (ns_uri, node_name)
Ejemplo n.º 8
0
    def setDefaultNamespace(self, default_namespace):
        """Set the default namespace for the generated document.

        Even if invoked post construction, the default namespace will affect
        the entire document, as all namespace declarations are placed in the
        document root.

        @param default_namespace: The namespace to be defined as the default
        namespace in the top-level element of the document.  May be provided
        as a real namespace, or just its URI.
        @type default_namespace: L{pyxb.namespace.Namespace} or C{str} or
        C{unicode}.
        """

        if isinstance(default_namespace, basestring):
            default_namespace = pyxb.namespace.NamespaceForURI(
                default_namespace, create_if_missing=True)
        if (default_namespace
                is not None) and default_namespace.isAbsentNamespace():
            raise pyxb.UsageError(
                'Default namespace must not be an absent namespace')
        self.__defaultNamespace = default_namespace