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