Patch #103885: Add dynamic registration and lookup of DOM implementations.
diff --git a/Doc/lib/xmldom.tex b/Doc/lib/xmldom.tex
index 5e752a0..87070b9 100644
--- a/Doc/lib/xmldom.tex
+++ b/Doc/lib/xmldom.tex
@@ -85,6 +85,36 @@
            {This specifies the mapping from OMG IDL to Python.}
 \end{seealso}
 
+\subsection{Module Contents}
+
+The \module{xml.dom} contains the following functions:
+
+\begin{funcdesc}{registerDOMImplementation}{name, factory}
+Register the \var{factory} function with the \var{name}. The factory
+function should return an object which implements the
+\code{DOMImplementation| interface. The factory function can either return
+the same object, or a new one (e.g. if that implementation supports
+some customization).
+\end{funcdesc}
+
+\begin{funcdesc}{getDOMImplementation}{name = None, features = ()}
+Return a suitable DOM implementation. The \var{name} is either
+well-known, the module name of a DOM implementation, or
+\code{None}. If it is not \code{None}, imports the corresponding module and
+returns a \class{DOMImplementation} object if the import succeeds.  If
+no name is given, and if the environment variable \code{PYTHON_DOM} is
+set, this variable is used to find the implementation.
+
+If name is not given, consider the available implementations to find
+one with the required feature set. If no implementation can be found,
+raise an \exception{ImportError}. The features list must be a sequence of
+(feature, version) pairs which are passed to hasFeature.
+\end{funcdesc}
+
+% Should the Node documentation go here?
+
+In addition, \module{xml.dom} contains the \class{Node}, and the DOM
+exceptions.
 
 \subsection{Objects in the DOM \label{dom-objects}}
 
diff --git a/Lib/xml/dom/__init__.py b/Lib/xml/dom/__init__.py
index 2dbb695..aa19ca1 100644
--- a/Lib/xml/dom/__init__.py
+++ b/Lib/xml/dom/__init__.py
@@ -115,3 +115,5 @@
 
 class InvalidAccessErr(DOMException):
     code = INVALID_ACCESS_ERR
+
+from domreg import getDOMImplementation,registerDOMImplementation
diff --git a/Lib/xml/dom/domreg.py b/Lib/xml/dom/domreg.py
new file mode 100644
index 0000000..14b87d6
--- /dev/null
+++ b/Lib/xml/dom/domreg.py
@@ -0,0 +1,76 @@
+"""Registration facilities for DOM. This module should not be used
+directly. Instead, the functions getDOMImplementation and
+registerDOMImplementation should be imported from xml.dom."""
+
+# This is a list of well-known implementations.  Well-known names
+# should be published by posting to xml-sig@python.org, and are
+# subsequently recorded in this file.
+
+well_known_implementations = {
+    'minidom':'xml.dom.minidom',
+    '4DOM': 'xml.dom.DOMImplementation',
+    }
+
+# DOM implementations not officially registered should register
+# themselves with their
+
+registered = {}
+
+def registerDOMImplementation(name, factory):
+    """registerDOMImplementation(name, factory)
+
+    Register the factory function with the name. The factory function
+    should return an object which implements the DOMImplementation
+    interface. The factory function can either return the same object,
+    or a new one (e.g. if that implementation supports some
+    customization)."""
+    
+    registered[name] = factory
+
+def _good_enough(dom, features):
+    "_good_enough(dom, features) -> Return 1 if the dom offers the features"
+    for f,v in features:
+        if not dom.hasFeature(f,v):
+            return 0
+    return 1
+
+def getDOMImplementation(name = None, features = ()):
+    """getDOMImplementation(name = None, features = ()) -> DOM implementation.
+
+    Return a suitable DOM implementation. The name is either
+    well-known, the module name of a DOM implementation, or None. If
+    it is not None, imports the corresponding module and returns
+    DOMImplementation object if the import succeeds.
+
+    If name is not given, consider the available implementations to
+    find one with the required feature set. If no implementation can
+    be found, raise an ImportError. The features list must be a sequence
+    of (feature, version) pairs which are passed to hasFeature."""
+    
+    import os
+    creator = None
+    mod = well_known_implementations.get(name)
+    if mod:
+        mod = __import__(mod, {}, {}, ['getDOMImplementation'])
+        return mod.getDOMImplementation()
+    elif name:
+        return registered[name]()
+    elif os.environ.has_key("PYTHON_DOM"):
+        return getDOMImplementation(name = os.environ["PYTHON_DOM"])
+
+    # User did not specify a name, try implementations in arbitrary
+    # order, returning the one that has the required features
+    for creator in registered.values():
+        dom = creator()
+        if _good_enough(dom, features):
+            return dom
+
+    for creator in well_known_implementations.keys():
+        try:
+            dom = getDOMImplementation(name = creator)
+        except StandardError: # typically ImportError, or AttributeError
+            continue
+        if _good_enough(dom, features):
+            return dom
+
+    raise ImportError,"no suitable DOM implementation found"
diff --git a/Lib/xml/dom/minidom.py b/Lib/xml/dom/minidom.py
index b4ae267..35adfd5 100644
--- a/Lib/xml/dom/minidom.py
+++ b/Lib/xml/dom/minidom.py
@@ -782,3 +782,6 @@
     """Parse a file into a DOM from a string."""
     from xml.dom import pulldom
     return _doparse(pulldom.parseString, args, kwargs)
+
+def getDOMImplementation():
+    return Document.implementation