xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/xml/dom/minidom.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1*cda5da8dSAndroid Build Coastguard Worker"""Simple implementation of the Level 1 DOM.
2*cda5da8dSAndroid Build Coastguard Worker
3*cda5da8dSAndroid Build Coastguard WorkerNamespaces and other minor Level 2 features are also supported.
4*cda5da8dSAndroid Build Coastguard Worker
5*cda5da8dSAndroid Build Coastguard Workerparse("foo.xml")
6*cda5da8dSAndroid Build Coastguard Worker
7*cda5da8dSAndroid Build Coastguard WorkerparseString("<foo><bar/></foo>")
8*cda5da8dSAndroid Build Coastguard Worker
9*cda5da8dSAndroid Build Coastguard WorkerTodo:
10*cda5da8dSAndroid Build Coastguard Worker=====
11*cda5da8dSAndroid Build Coastguard Worker * convenience methods for getting elements and text.
12*cda5da8dSAndroid Build Coastguard Worker * more testing
13*cda5da8dSAndroid Build Coastguard Worker * bring some of the writer and linearizer code into conformance with this
14*cda5da8dSAndroid Build Coastguard Worker        interface
15*cda5da8dSAndroid Build Coastguard Worker * SAX 2 namespaces
16*cda5da8dSAndroid Build Coastguard Worker"""
17*cda5da8dSAndroid Build Coastguard Worker
18*cda5da8dSAndroid Build Coastguard Workerimport io
19*cda5da8dSAndroid Build Coastguard Workerimport xml.dom
20*cda5da8dSAndroid Build Coastguard Worker
21*cda5da8dSAndroid Build Coastguard Workerfrom xml.dom import EMPTY_NAMESPACE, EMPTY_PREFIX, XMLNS_NAMESPACE, domreg
22*cda5da8dSAndroid Build Coastguard Workerfrom xml.dom.minicompat import *
23*cda5da8dSAndroid Build Coastguard Workerfrom xml.dom.xmlbuilder import DOMImplementationLS, DocumentLS
24*cda5da8dSAndroid Build Coastguard Worker
25*cda5da8dSAndroid Build Coastguard Worker# This is used by the ID-cache invalidation checks; the list isn't
26*cda5da8dSAndroid Build Coastguard Worker# actually complete, since the nodes being checked will never be the
27*cda5da8dSAndroid Build Coastguard Worker# DOCUMENT_NODE or DOCUMENT_FRAGMENT_NODE.  (The node being checked is
28*cda5da8dSAndroid Build Coastguard Worker# the node being added or removed, not the node being modified.)
29*cda5da8dSAndroid Build Coastguard Worker#
30*cda5da8dSAndroid Build Coastguard Worker_nodeTypes_with_children = (xml.dom.Node.ELEMENT_NODE,
31*cda5da8dSAndroid Build Coastguard Worker                            xml.dom.Node.ENTITY_REFERENCE_NODE)
32*cda5da8dSAndroid Build Coastguard Worker
33*cda5da8dSAndroid Build Coastguard Worker
34*cda5da8dSAndroid Build Coastguard Workerclass Node(xml.dom.Node):
35*cda5da8dSAndroid Build Coastguard Worker    namespaceURI = None # this is non-null only for elements and attributes
36*cda5da8dSAndroid Build Coastguard Worker    parentNode = None
37*cda5da8dSAndroid Build Coastguard Worker    ownerDocument = None
38*cda5da8dSAndroid Build Coastguard Worker    nextSibling = None
39*cda5da8dSAndroid Build Coastguard Worker    previousSibling = None
40*cda5da8dSAndroid Build Coastguard Worker
41*cda5da8dSAndroid Build Coastguard Worker    prefix = EMPTY_PREFIX # non-null only for NS elements and attributes
42*cda5da8dSAndroid Build Coastguard Worker
43*cda5da8dSAndroid Build Coastguard Worker    def __bool__(self):
44*cda5da8dSAndroid Build Coastguard Worker        return True
45*cda5da8dSAndroid Build Coastguard Worker
46*cda5da8dSAndroid Build Coastguard Worker    def toxml(self, encoding=None, standalone=None):
47*cda5da8dSAndroid Build Coastguard Worker        return self.toprettyxml("", "", encoding, standalone)
48*cda5da8dSAndroid Build Coastguard Worker
49*cda5da8dSAndroid Build Coastguard Worker    def toprettyxml(self, indent="\t", newl="\n", encoding=None,
50*cda5da8dSAndroid Build Coastguard Worker                    standalone=None):
51*cda5da8dSAndroid Build Coastguard Worker        if encoding is None:
52*cda5da8dSAndroid Build Coastguard Worker            writer = io.StringIO()
53*cda5da8dSAndroid Build Coastguard Worker        else:
54*cda5da8dSAndroid Build Coastguard Worker            writer = io.TextIOWrapper(io.BytesIO(),
55*cda5da8dSAndroid Build Coastguard Worker                                      encoding=encoding,
56*cda5da8dSAndroid Build Coastguard Worker                                      errors="xmlcharrefreplace",
57*cda5da8dSAndroid Build Coastguard Worker                                      newline='\n')
58*cda5da8dSAndroid Build Coastguard Worker        if self.nodeType == Node.DOCUMENT_NODE:
59*cda5da8dSAndroid Build Coastguard Worker            # Can pass encoding only to document, to put it into XML header
60*cda5da8dSAndroid Build Coastguard Worker            self.writexml(writer, "", indent, newl, encoding, standalone)
61*cda5da8dSAndroid Build Coastguard Worker        else:
62*cda5da8dSAndroid Build Coastguard Worker            self.writexml(writer, "", indent, newl)
63*cda5da8dSAndroid Build Coastguard Worker        if encoding is None:
64*cda5da8dSAndroid Build Coastguard Worker            return writer.getvalue()
65*cda5da8dSAndroid Build Coastguard Worker        else:
66*cda5da8dSAndroid Build Coastguard Worker            return writer.detach().getvalue()
67*cda5da8dSAndroid Build Coastguard Worker
68*cda5da8dSAndroid Build Coastguard Worker    def hasChildNodes(self):
69*cda5da8dSAndroid Build Coastguard Worker        return bool(self.childNodes)
70*cda5da8dSAndroid Build Coastguard Worker
71*cda5da8dSAndroid Build Coastguard Worker    def _get_childNodes(self):
72*cda5da8dSAndroid Build Coastguard Worker        return self.childNodes
73*cda5da8dSAndroid Build Coastguard Worker
74*cda5da8dSAndroid Build Coastguard Worker    def _get_firstChild(self):
75*cda5da8dSAndroid Build Coastguard Worker        if self.childNodes:
76*cda5da8dSAndroid Build Coastguard Worker            return self.childNodes[0]
77*cda5da8dSAndroid Build Coastguard Worker
78*cda5da8dSAndroid Build Coastguard Worker    def _get_lastChild(self):
79*cda5da8dSAndroid Build Coastguard Worker        if self.childNodes:
80*cda5da8dSAndroid Build Coastguard Worker            return self.childNodes[-1]
81*cda5da8dSAndroid Build Coastguard Worker
82*cda5da8dSAndroid Build Coastguard Worker    def insertBefore(self, newChild, refChild):
83*cda5da8dSAndroid Build Coastguard Worker        if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
84*cda5da8dSAndroid Build Coastguard Worker            for c in tuple(newChild.childNodes):
85*cda5da8dSAndroid Build Coastguard Worker                self.insertBefore(c, refChild)
86*cda5da8dSAndroid Build Coastguard Worker            ### The DOM does not clearly specify what to return in this case
87*cda5da8dSAndroid Build Coastguard Worker            return newChild
88*cda5da8dSAndroid Build Coastguard Worker        if newChild.nodeType not in self._child_node_types:
89*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.HierarchyRequestErr(
90*cda5da8dSAndroid Build Coastguard Worker                "%s cannot be child of %s" % (repr(newChild), repr(self)))
91*cda5da8dSAndroid Build Coastguard Worker        if newChild.parentNode is not None:
92*cda5da8dSAndroid Build Coastguard Worker            newChild.parentNode.removeChild(newChild)
93*cda5da8dSAndroid Build Coastguard Worker        if refChild is None:
94*cda5da8dSAndroid Build Coastguard Worker            self.appendChild(newChild)
95*cda5da8dSAndroid Build Coastguard Worker        else:
96*cda5da8dSAndroid Build Coastguard Worker            try:
97*cda5da8dSAndroid Build Coastguard Worker                index = self.childNodes.index(refChild)
98*cda5da8dSAndroid Build Coastguard Worker            except ValueError:
99*cda5da8dSAndroid Build Coastguard Worker                raise xml.dom.NotFoundErr()
100*cda5da8dSAndroid Build Coastguard Worker            if newChild.nodeType in _nodeTypes_with_children:
101*cda5da8dSAndroid Build Coastguard Worker                _clear_id_cache(self)
102*cda5da8dSAndroid Build Coastguard Worker            self.childNodes.insert(index, newChild)
103*cda5da8dSAndroid Build Coastguard Worker            newChild.nextSibling = refChild
104*cda5da8dSAndroid Build Coastguard Worker            refChild.previousSibling = newChild
105*cda5da8dSAndroid Build Coastguard Worker            if index:
106*cda5da8dSAndroid Build Coastguard Worker                node = self.childNodes[index-1]
107*cda5da8dSAndroid Build Coastguard Worker                node.nextSibling = newChild
108*cda5da8dSAndroid Build Coastguard Worker                newChild.previousSibling = node
109*cda5da8dSAndroid Build Coastguard Worker            else:
110*cda5da8dSAndroid Build Coastguard Worker                newChild.previousSibling = None
111*cda5da8dSAndroid Build Coastguard Worker            newChild.parentNode = self
112*cda5da8dSAndroid Build Coastguard Worker        return newChild
113*cda5da8dSAndroid Build Coastguard Worker
114*cda5da8dSAndroid Build Coastguard Worker    def appendChild(self, node):
115*cda5da8dSAndroid Build Coastguard Worker        if node.nodeType == self.DOCUMENT_FRAGMENT_NODE:
116*cda5da8dSAndroid Build Coastguard Worker            for c in tuple(node.childNodes):
117*cda5da8dSAndroid Build Coastguard Worker                self.appendChild(c)
118*cda5da8dSAndroid Build Coastguard Worker            ### The DOM does not clearly specify what to return in this case
119*cda5da8dSAndroid Build Coastguard Worker            return node
120*cda5da8dSAndroid Build Coastguard Worker        if node.nodeType not in self._child_node_types:
121*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.HierarchyRequestErr(
122*cda5da8dSAndroid Build Coastguard Worker                "%s cannot be child of %s" % (repr(node), repr(self)))
123*cda5da8dSAndroid Build Coastguard Worker        elif node.nodeType in _nodeTypes_with_children:
124*cda5da8dSAndroid Build Coastguard Worker            _clear_id_cache(self)
125*cda5da8dSAndroid Build Coastguard Worker        if node.parentNode is not None:
126*cda5da8dSAndroid Build Coastguard Worker            node.parentNode.removeChild(node)
127*cda5da8dSAndroid Build Coastguard Worker        _append_child(self, node)
128*cda5da8dSAndroid Build Coastguard Worker        node.nextSibling = None
129*cda5da8dSAndroid Build Coastguard Worker        return node
130*cda5da8dSAndroid Build Coastguard Worker
131*cda5da8dSAndroid Build Coastguard Worker    def replaceChild(self, newChild, oldChild):
132*cda5da8dSAndroid Build Coastguard Worker        if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
133*cda5da8dSAndroid Build Coastguard Worker            refChild = oldChild.nextSibling
134*cda5da8dSAndroid Build Coastguard Worker            self.removeChild(oldChild)
135*cda5da8dSAndroid Build Coastguard Worker            return self.insertBefore(newChild, refChild)
136*cda5da8dSAndroid Build Coastguard Worker        if newChild.nodeType not in self._child_node_types:
137*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.HierarchyRequestErr(
138*cda5da8dSAndroid Build Coastguard Worker                "%s cannot be child of %s" % (repr(newChild), repr(self)))
139*cda5da8dSAndroid Build Coastguard Worker        if newChild is oldChild:
140*cda5da8dSAndroid Build Coastguard Worker            return
141*cda5da8dSAndroid Build Coastguard Worker        if newChild.parentNode is not None:
142*cda5da8dSAndroid Build Coastguard Worker            newChild.parentNode.removeChild(newChild)
143*cda5da8dSAndroid Build Coastguard Worker        try:
144*cda5da8dSAndroid Build Coastguard Worker            index = self.childNodes.index(oldChild)
145*cda5da8dSAndroid Build Coastguard Worker        except ValueError:
146*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.NotFoundErr()
147*cda5da8dSAndroid Build Coastguard Worker        self.childNodes[index] = newChild
148*cda5da8dSAndroid Build Coastguard Worker        newChild.parentNode = self
149*cda5da8dSAndroid Build Coastguard Worker        oldChild.parentNode = None
150*cda5da8dSAndroid Build Coastguard Worker        if (newChild.nodeType in _nodeTypes_with_children
151*cda5da8dSAndroid Build Coastguard Worker            or oldChild.nodeType in _nodeTypes_with_children):
152*cda5da8dSAndroid Build Coastguard Worker            _clear_id_cache(self)
153*cda5da8dSAndroid Build Coastguard Worker        newChild.nextSibling = oldChild.nextSibling
154*cda5da8dSAndroid Build Coastguard Worker        newChild.previousSibling = oldChild.previousSibling
155*cda5da8dSAndroid Build Coastguard Worker        oldChild.nextSibling = None
156*cda5da8dSAndroid Build Coastguard Worker        oldChild.previousSibling = None
157*cda5da8dSAndroid Build Coastguard Worker        if newChild.previousSibling:
158*cda5da8dSAndroid Build Coastguard Worker            newChild.previousSibling.nextSibling = newChild
159*cda5da8dSAndroid Build Coastguard Worker        if newChild.nextSibling:
160*cda5da8dSAndroid Build Coastguard Worker            newChild.nextSibling.previousSibling = newChild
161*cda5da8dSAndroid Build Coastguard Worker        return oldChild
162*cda5da8dSAndroid Build Coastguard Worker
163*cda5da8dSAndroid Build Coastguard Worker    def removeChild(self, oldChild):
164*cda5da8dSAndroid Build Coastguard Worker        try:
165*cda5da8dSAndroid Build Coastguard Worker            self.childNodes.remove(oldChild)
166*cda5da8dSAndroid Build Coastguard Worker        except ValueError:
167*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.NotFoundErr()
168*cda5da8dSAndroid Build Coastguard Worker        if oldChild.nextSibling is not None:
169*cda5da8dSAndroid Build Coastguard Worker            oldChild.nextSibling.previousSibling = oldChild.previousSibling
170*cda5da8dSAndroid Build Coastguard Worker        if oldChild.previousSibling is not None:
171*cda5da8dSAndroid Build Coastguard Worker            oldChild.previousSibling.nextSibling = oldChild.nextSibling
172*cda5da8dSAndroid Build Coastguard Worker        oldChild.nextSibling = oldChild.previousSibling = None
173*cda5da8dSAndroid Build Coastguard Worker        if oldChild.nodeType in _nodeTypes_with_children:
174*cda5da8dSAndroid Build Coastguard Worker            _clear_id_cache(self)
175*cda5da8dSAndroid Build Coastguard Worker
176*cda5da8dSAndroid Build Coastguard Worker        oldChild.parentNode = None
177*cda5da8dSAndroid Build Coastguard Worker        return oldChild
178*cda5da8dSAndroid Build Coastguard Worker
179*cda5da8dSAndroid Build Coastguard Worker    def normalize(self):
180*cda5da8dSAndroid Build Coastguard Worker        L = []
181*cda5da8dSAndroid Build Coastguard Worker        for child in self.childNodes:
182*cda5da8dSAndroid Build Coastguard Worker            if child.nodeType == Node.TEXT_NODE:
183*cda5da8dSAndroid Build Coastguard Worker                if not child.data:
184*cda5da8dSAndroid Build Coastguard Worker                    # empty text node; discard
185*cda5da8dSAndroid Build Coastguard Worker                    if L:
186*cda5da8dSAndroid Build Coastguard Worker                        L[-1].nextSibling = child.nextSibling
187*cda5da8dSAndroid Build Coastguard Worker                    if child.nextSibling:
188*cda5da8dSAndroid Build Coastguard Worker                        child.nextSibling.previousSibling = child.previousSibling
189*cda5da8dSAndroid Build Coastguard Worker                    child.unlink()
190*cda5da8dSAndroid Build Coastguard Worker                elif L and L[-1].nodeType == child.nodeType:
191*cda5da8dSAndroid Build Coastguard Worker                    # collapse text node
192*cda5da8dSAndroid Build Coastguard Worker                    node = L[-1]
193*cda5da8dSAndroid Build Coastguard Worker                    node.data = node.data + child.data
194*cda5da8dSAndroid Build Coastguard Worker                    node.nextSibling = child.nextSibling
195*cda5da8dSAndroid Build Coastguard Worker                    if child.nextSibling:
196*cda5da8dSAndroid Build Coastguard Worker                        child.nextSibling.previousSibling = node
197*cda5da8dSAndroid Build Coastguard Worker                    child.unlink()
198*cda5da8dSAndroid Build Coastguard Worker                else:
199*cda5da8dSAndroid Build Coastguard Worker                    L.append(child)
200*cda5da8dSAndroid Build Coastguard Worker            else:
201*cda5da8dSAndroid Build Coastguard Worker                L.append(child)
202*cda5da8dSAndroid Build Coastguard Worker                if child.nodeType == Node.ELEMENT_NODE:
203*cda5da8dSAndroid Build Coastguard Worker                    child.normalize()
204*cda5da8dSAndroid Build Coastguard Worker        self.childNodes[:] = L
205*cda5da8dSAndroid Build Coastguard Worker
206*cda5da8dSAndroid Build Coastguard Worker    def cloneNode(self, deep):
207*cda5da8dSAndroid Build Coastguard Worker        return _clone_node(self, deep, self.ownerDocument or self)
208*cda5da8dSAndroid Build Coastguard Worker
209*cda5da8dSAndroid Build Coastguard Worker    def isSupported(self, feature, version):
210*cda5da8dSAndroid Build Coastguard Worker        return self.ownerDocument.implementation.hasFeature(feature, version)
211*cda5da8dSAndroid Build Coastguard Worker
212*cda5da8dSAndroid Build Coastguard Worker    def _get_localName(self):
213*cda5da8dSAndroid Build Coastguard Worker        # Overridden in Element and Attr where localName can be Non-Null
214*cda5da8dSAndroid Build Coastguard Worker        return None
215*cda5da8dSAndroid Build Coastguard Worker
216*cda5da8dSAndroid Build Coastguard Worker    # Node interfaces from Level 3 (WD 9 April 2002)
217*cda5da8dSAndroid Build Coastguard Worker
218*cda5da8dSAndroid Build Coastguard Worker    def isSameNode(self, other):
219*cda5da8dSAndroid Build Coastguard Worker        return self is other
220*cda5da8dSAndroid Build Coastguard Worker
221*cda5da8dSAndroid Build Coastguard Worker    def getInterface(self, feature):
222*cda5da8dSAndroid Build Coastguard Worker        if self.isSupported(feature, None):
223*cda5da8dSAndroid Build Coastguard Worker            return self
224*cda5da8dSAndroid Build Coastguard Worker        else:
225*cda5da8dSAndroid Build Coastguard Worker            return None
226*cda5da8dSAndroid Build Coastguard Worker
227*cda5da8dSAndroid Build Coastguard Worker    # The "user data" functions use a dictionary that is only present
228*cda5da8dSAndroid Build Coastguard Worker    # if some user data has been set, so be careful not to assume it
229*cda5da8dSAndroid Build Coastguard Worker    # exists.
230*cda5da8dSAndroid Build Coastguard Worker
231*cda5da8dSAndroid Build Coastguard Worker    def getUserData(self, key):
232*cda5da8dSAndroid Build Coastguard Worker        try:
233*cda5da8dSAndroid Build Coastguard Worker            return self._user_data[key][0]
234*cda5da8dSAndroid Build Coastguard Worker        except (AttributeError, KeyError):
235*cda5da8dSAndroid Build Coastguard Worker            return None
236*cda5da8dSAndroid Build Coastguard Worker
237*cda5da8dSAndroid Build Coastguard Worker    def setUserData(self, key, data, handler):
238*cda5da8dSAndroid Build Coastguard Worker        old = None
239*cda5da8dSAndroid Build Coastguard Worker        try:
240*cda5da8dSAndroid Build Coastguard Worker            d = self._user_data
241*cda5da8dSAndroid Build Coastguard Worker        except AttributeError:
242*cda5da8dSAndroid Build Coastguard Worker            d = {}
243*cda5da8dSAndroid Build Coastguard Worker            self._user_data = d
244*cda5da8dSAndroid Build Coastguard Worker        if key in d:
245*cda5da8dSAndroid Build Coastguard Worker            old = d[key][0]
246*cda5da8dSAndroid Build Coastguard Worker        if data is None:
247*cda5da8dSAndroid Build Coastguard Worker            # ignore handlers passed for None
248*cda5da8dSAndroid Build Coastguard Worker            handler = None
249*cda5da8dSAndroid Build Coastguard Worker            if old is not None:
250*cda5da8dSAndroid Build Coastguard Worker                del d[key]
251*cda5da8dSAndroid Build Coastguard Worker        else:
252*cda5da8dSAndroid Build Coastguard Worker            d[key] = (data, handler)
253*cda5da8dSAndroid Build Coastguard Worker        return old
254*cda5da8dSAndroid Build Coastguard Worker
255*cda5da8dSAndroid Build Coastguard Worker    def _call_user_data_handler(self, operation, src, dst):
256*cda5da8dSAndroid Build Coastguard Worker        if hasattr(self, "_user_data"):
257*cda5da8dSAndroid Build Coastguard Worker            for key, (data, handler) in list(self._user_data.items()):
258*cda5da8dSAndroid Build Coastguard Worker                if handler is not None:
259*cda5da8dSAndroid Build Coastguard Worker                    handler.handle(operation, key, data, src, dst)
260*cda5da8dSAndroid Build Coastguard Worker
261*cda5da8dSAndroid Build Coastguard Worker    # minidom-specific API:
262*cda5da8dSAndroid Build Coastguard Worker
263*cda5da8dSAndroid Build Coastguard Worker    def unlink(self):
264*cda5da8dSAndroid Build Coastguard Worker        self.parentNode = self.ownerDocument = None
265*cda5da8dSAndroid Build Coastguard Worker        if self.childNodes:
266*cda5da8dSAndroid Build Coastguard Worker            for child in self.childNodes:
267*cda5da8dSAndroid Build Coastguard Worker                child.unlink()
268*cda5da8dSAndroid Build Coastguard Worker            self.childNodes = NodeList()
269*cda5da8dSAndroid Build Coastguard Worker        self.previousSibling = None
270*cda5da8dSAndroid Build Coastguard Worker        self.nextSibling = None
271*cda5da8dSAndroid Build Coastguard Worker
272*cda5da8dSAndroid Build Coastguard Worker    # A Node is its own context manager, to ensure that an unlink() call occurs.
273*cda5da8dSAndroid Build Coastguard Worker    # This is similar to how a file object works.
274*cda5da8dSAndroid Build Coastguard Worker    def __enter__(self):
275*cda5da8dSAndroid Build Coastguard Worker        return self
276*cda5da8dSAndroid Build Coastguard Worker
277*cda5da8dSAndroid Build Coastguard Worker    def __exit__(self, et, ev, tb):
278*cda5da8dSAndroid Build Coastguard Worker        self.unlink()
279*cda5da8dSAndroid Build Coastguard Worker
280*cda5da8dSAndroid Build Coastguard Workerdefproperty(Node, "firstChild", doc="First child node, or None.")
281*cda5da8dSAndroid Build Coastguard Workerdefproperty(Node, "lastChild",  doc="Last child node, or None.")
282*cda5da8dSAndroid Build Coastguard Workerdefproperty(Node, "localName",  doc="Namespace-local name of this node.")
283*cda5da8dSAndroid Build Coastguard Worker
284*cda5da8dSAndroid Build Coastguard Worker
285*cda5da8dSAndroid Build Coastguard Workerdef _append_child(self, node):
286*cda5da8dSAndroid Build Coastguard Worker    # fast path with less checks; usable by DOM builders if careful
287*cda5da8dSAndroid Build Coastguard Worker    childNodes = self.childNodes
288*cda5da8dSAndroid Build Coastguard Worker    if childNodes:
289*cda5da8dSAndroid Build Coastguard Worker        last = childNodes[-1]
290*cda5da8dSAndroid Build Coastguard Worker        node.previousSibling = last
291*cda5da8dSAndroid Build Coastguard Worker        last.nextSibling = node
292*cda5da8dSAndroid Build Coastguard Worker    childNodes.append(node)
293*cda5da8dSAndroid Build Coastguard Worker    node.parentNode = self
294*cda5da8dSAndroid Build Coastguard Worker
295*cda5da8dSAndroid Build Coastguard Workerdef _in_document(node):
296*cda5da8dSAndroid Build Coastguard Worker    # return True iff node is part of a document tree
297*cda5da8dSAndroid Build Coastguard Worker    while node is not None:
298*cda5da8dSAndroid Build Coastguard Worker        if node.nodeType == Node.DOCUMENT_NODE:
299*cda5da8dSAndroid Build Coastguard Worker            return True
300*cda5da8dSAndroid Build Coastguard Worker        node = node.parentNode
301*cda5da8dSAndroid Build Coastguard Worker    return False
302*cda5da8dSAndroid Build Coastguard Worker
303*cda5da8dSAndroid Build Coastguard Workerdef _write_data(writer, data):
304*cda5da8dSAndroid Build Coastguard Worker    "Writes datachars to writer."
305*cda5da8dSAndroid Build Coastguard Worker    if data:
306*cda5da8dSAndroid Build Coastguard Worker        data = data.replace("&", "&amp;").replace("<", "&lt;"). \
307*cda5da8dSAndroid Build Coastguard Worker                    replace("\"", "&quot;").replace(">", "&gt;")
308*cda5da8dSAndroid Build Coastguard Worker        writer.write(data)
309*cda5da8dSAndroid Build Coastguard Worker
310*cda5da8dSAndroid Build Coastguard Workerdef _get_elements_by_tagName_helper(parent, name, rc):
311*cda5da8dSAndroid Build Coastguard Worker    for node in parent.childNodes:
312*cda5da8dSAndroid Build Coastguard Worker        if node.nodeType == Node.ELEMENT_NODE and \
313*cda5da8dSAndroid Build Coastguard Worker            (name == "*" or node.tagName == name):
314*cda5da8dSAndroid Build Coastguard Worker            rc.append(node)
315*cda5da8dSAndroid Build Coastguard Worker        _get_elements_by_tagName_helper(node, name, rc)
316*cda5da8dSAndroid Build Coastguard Worker    return rc
317*cda5da8dSAndroid Build Coastguard Worker
318*cda5da8dSAndroid Build Coastguard Workerdef _get_elements_by_tagName_ns_helper(parent, nsURI, localName, rc):
319*cda5da8dSAndroid Build Coastguard Worker    for node in parent.childNodes:
320*cda5da8dSAndroid Build Coastguard Worker        if node.nodeType == Node.ELEMENT_NODE:
321*cda5da8dSAndroid Build Coastguard Worker            if ((localName == "*" or node.localName == localName) and
322*cda5da8dSAndroid Build Coastguard Worker                (nsURI == "*" or node.namespaceURI == nsURI)):
323*cda5da8dSAndroid Build Coastguard Worker                rc.append(node)
324*cda5da8dSAndroid Build Coastguard Worker            _get_elements_by_tagName_ns_helper(node, nsURI, localName, rc)
325*cda5da8dSAndroid Build Coastguard Worker    return rc
326*cda5da8dSAndroid Build Coastguard Worker
327*cda5da8dSAndroid Build Coastguard Workerclass DocumentFragment(Node):
328*cda5da8dSAndroid Build Coastguard Worker    nodeType = Node.DOCUMENT_FRAGMENT_NODE
329*cda5da8dSAndroid Build Coastguard Worker    nodeName = "#document-fragment"
330*cda5da8dSAndroid Build Coastguard Worker    nodeValue = None
331*cda5da8dSAndroid Build Coastguard Worker    attributes = None
332*cda5da8dSAndroid Build Coastguard Worker    parentNode = None
333*cda5da8dSAndroid Build Coastguard Worker    _child_node_types = (Node.ELEMENT_NODE,
334*cda5da8dSAndroid Build Coastguard Worker                         Node.TEXT_NODE,
335*cda5da8dSAndroid Build Coastguard Worker                         Node.CDATA_SECTION_NODE,
336*cda5da8dSAndroid Build Coastguard Worker                         Node.ENTITY_REFERENCE_NODE,
337*cda5da8dSAndroid Build Coastguard Worker                         Node.PROCESSING_INSTRUCTION_NODE,
338*cda5da8dSAndroid Build Coastguard Worker                         Node.COMMENT_NODE,
339*cda5da8dSAndroid Build Coastguard Worker                         Node.NOTATION_NODE)
340*cda5da8dSAndroid Build Coastguard Worker
341*cda5da8dSAndroid Build Coastguard Worker    def __init__(self):
342*cda5da8dSAndroid Build Coastguard Worker        self.childNodes = NodeList()
343*cda5da8dSAndroid Build Coastguard Worker
344*cda5da8dSAndroid Build Coastguard Worker
345*cda5da8dSAndroid Build Coastguard Workerclass Attr(Node):
346*cda5da8dSAndroid Build Coastguard Worker    __slots__=('_name', '_value', 'namespaceURI',
347*cda5da8dSAndroid Build Coastguard Worker               '_prefix', 'childNodes', '_localName', 'ownerDocument', 'ownerElement')
348*cda5da8dSAndroid Build Coastguard Worker    nodeType = Node.ATTRIBUTE_NODE
349*cda5da8dSAndroid Build Coastguard Worker    attributes = None
350*cda5da8dSAndroid Build Coastguard Worker    specified = False
351*cda5da8dSAndroid Build Coastguard Worker    _is_id = False
352*cda5da8dSAndroid Build Coastguard Worker
353*cda5da8dSAndroid Build Coastguard Worker    _child_node_types = (Node.TEXT_NODE, Node.ENTITY_REFERENCE_NODE)
354*cda5da8dSAndroid Build Coastguard Worker
355*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None,
356*cda5da8dSAndroid Build Coastguard Worker                 prefix=None):
357*cda5da8dSAndroid Build Coastguard Worker        self.ownerElement = None
358*cda5da8dSAndroid Build Coastguard Worker        self._name = qName
359*cda5da8dSAndroid Build Coastguard Worker        self.namespaceURI = namespaceURI
360*cda5da8dSAndroid Build Coastguard Worker        self._prefix = prefix
361*cda5da8dSAndroid Build Coastguard Worker        if localName is not None:
362*cda5da8dSAndroid Build Coastguard Worker            self._localName = localName
363*cda5da8dSAndroid Build Coastguard Worker        self.childNodes = NodeList()
364*cda5da8dSAndroid Build Coastguard Worker
365*cda5da8dSAndroid Build Coastguard Worker        # Add the single child node that represents the value of the attr
366*cda5da8dSAndroid Build Coastguard Worker        self.childNodes.append(Text())
367*cda5da8dSAndroid Build Coastguard Worker
368*cda5da8dSAndroid Build Coastguard Worker        # nodeValue and value are set elsewhere
369*cda5da8dSAndroid Build Coastguard Worker
370*cda5da8dSAndroid Build Coastguard Worker    def _get_localName(self):
371*cda5da8dSAndroid Build Coastguard Worker        try:
372*cda5da8dSAndroid Build Coastguard Worker            return self._localName
373*cda5da8dSAndroid Build Coastguard Worker        except AttributeError:
374*cda5da8dSAndroid Build Coastguard Worker            return self.nodeName.split(":", 1)[-1]
375*cda5da8dSAndroid Build Coastguard Worker
376*cda5da8dSAndroid Build Coastguard Worker    def _get_specified(self):
377*cda5da8dSAndroid Build Coastguard Worker        return self.specified
378*cda5da8dSAndroid Build Coastguard Worker
379*cda5da8dSAndroid Build Coastguard Worker    def _get_name(self):
380*cda5da8dSAndroid Build Coastguard Worker        return self._name
381*cda5da8dSAndroid Build Coastguard Worker
382*cda5da8dSAndroid Build Coastguard Worker    def _set_name(self, value):
383*cda5da8dSAndroid Build Coastguard Worker        self._name = value
384*cda5da8dSAndroid Build Coastguard Worker        if self.ownerElement is not None:
385*cda5da8dSAndroid Build Coastguard Worker            _clear_id_cache(self.ownerElement)
386*cda5da8dSAndroid Build Coastguard Worker
387*cda5da8dSAndroid Build Coastguard Worker    nodeName = name = property(_get_name, _set_name)
388*cda5da8dSAndroid Build Coastguard Worker
389*cda5da8dSAndroid Build Coastguard Worker    def _get_value(self):
390*cda5da8dSAndroid Build Coastguard Worker        return self._value
391*cda5da8dSAndroid Build Coastguard Worker
392*cda5da8dSAndroid Build Coastguard Worker    def _set_value(self, value):
393*cda5da8dSAndroid Build Coastguard Worker        self._value = value
394*cda5da8dSAndroid Build Coastguard Worker        self.childNodes[0].data = value
395*cda5da8dSAndroid Build Coastguard Worker        if self.ownerElement is not None:
396*cda5da8dSAndroid Build Coastguard Worker            _clear_id_cache(self.ownerElement)
397*cda5da8dSAndroid Build Coastguard Worker        self.childNodes[0].data = value
398*cda5da8dSAndroid Build Coastguard Worker
399*cda5da8dSAndroid Build Coastguard Worker    nodeValue = value = property(_get_value, _set_value)
400*cda5da8dSAndroid Build Coastguard Worker
401*cda5da8dSAndroid Build Coastguard Worker    def _get_prefix(self):
402*cda5da8dSAndroid Build Coastguard Worker        return self._prefix
403*cda5da8dSAndroid Build Coastguard Worker
404*cda5da8dSAndroid Build Coastguard Worker    def _set_prefix(self, prefix):
405*cda5da8dSAndroid Build Coastguard Worker        nsuri = self.namespaceURI
406*cda5da8dSAndroid Build Coastguard Worker        if prefix == "xmlns":
407*cda5da8dSAndroid Build Coastguard Worker            if nsuri and nsuri != XMLNS_NAMESPACE:
408*cda5da8dSAndroid Build Coastguard Worker                raise xml.dom.NamespaceErr(
409*cda5da8dSAndroid Build Coastguard Worker                    "illegal use of 'xmlns' prefix for the wrong namespace")
410*cda5da8dSAndroid Build Coastguard Worker        self._prefix = prefix
411*cda5da8dSAndroid Build Coastguard Worker        if prefix is None:
412*cda5da8dSAndroid Build Coastguard Worker            newName = self.localName
413*cda5da8dSAndroid Build Coastguard Worker        else:
414*cda5da8dSAndroid Build Coastguard Worker            newName = "%s:%s" % (prefix, self.localName)
415*cda5da8dSAndroid Build Coastguard Worker        if self.ownerElement:
416*cda5da8dSAndroid Build Coastguard Worker            _clear_id_cache(self.ownerElement)
417*cda5da8dSAndroid Build Coastguard Worker        self.name = newName
418*cda5da8dSAndroid Build Coastguard Worker
419*cda5da8dSAndroid Build Coastguard Worker    prefix = property(_get_prefix, _set_prefix)
420*cda5da8dSAndroid Build Coastguard Worker
421*cda5da8dSAndroid Build Coastguard Worker    def unlink(self):
422*cda5da8dSAndroid Build Coastguard Worker        # This implementation does not call the base implementation
423*cda5da8dSAndroid Build Coastguard Worker        # since most of that is not needed, and the expense of the
424*cda5da8dSAndroid Build Coastguard Worker        # method call is not warranted.  We duplicate the removal of
425*cda5da8dSAndroid Build Coastguard Worker        # children, but that's all we needed from the base class.
426*cda5da8dSAndroid Build Coastguard Worker        elem = self.ownerElement
427*cda5da8dSAndroid Build Coastguard Worker        if elem is not None:
428*cda5da8dSAndroid Build Coastguard Worker            del elem._attrs[self.nodeName]
429*cda5da8dSAndroid Build Coastguard Worker            del elem._attrsNS[(self.namespaceURI, self.localName)]
430*cda5da8dSAndroid Build Coastguard Worker            if self._is_id:
431*cda5da8dSAndroid Build Coastguard Worker                self._is_id = False
432*cda5da8dSAndroid Build Coastguard Worker                elem._magic_id_nodes -= 1
433*cda5da8dSAndroid Build Coastguard Worker                self.ownerDocument._magic_id_count -= 1
434*cda5da8dSAndroid Build Coastguard Worker        for child in self.childNodes:
435*cda5da8dSAndroid Build Coastguard Worker            child.unlink()
436*cda5da8dSAndroid Build Coastguard Worker        del self.childNodes[:]
437*cda5da8dSAndroid Build Coastguard Worker
438*cda5da8dSAndroid Build Coastguard Worker    def _get_isId(self):
439*cda5da8dSAndroid Build Coastguard Worker        if self._is_id:
440*cda5da8dSAndroid Build Coastguard Worker            return True
441*cda5da8dSAndroid Build Coastguard Worker        doc = self.ownerDocument
442*cda5da8dSAndroid Build Coastguard Worker        elem = self.ownerElement
443*cda5da8dSAndroid Build Coastguard Worker        if doc is None or elem is None:
444*cda5da8dSAndroid Build Coastguard Worker            return False
445*cda5da8dSAndroid Build Coastguard Worker
446*cda5da8dSAndroid Build Coastguard Worker        info = doc._get_elem_info(elem)
447*cda5da8dSAndroid Build Coastguard Worker        if info is None:
448*cda5da8dSAndroid Build Coastguard Worker            return False
449*cda5da8dSAndroid Build Coastguard Worker        if self.namespaceURI:
450*cda5da8dSAndroid Build Coastguard Worker            return info.isIdNS(self.namespaceURI, self.localName)
451*cda5da8dSAndroid Build Coastguard Worker        else:
452*cda5da8dSAndroid Build Coastguard Worker            return info.isId(self.nodeName)
453*cda5da8dSAndroid Build Coastguard Worker
454*cda5da8dSAndroid Build Coastguard Worker    def _get_schemaType(self):
455*cda5da8dSAndroid Build Coastguard Worker        doc = self.ownerDocument
456*cda5da8dSAndroid Build Coastguard Worker        elem = self.ownerElement
457*cda5da8dSAndroid Build Coastguard Worker        if doc is None or elem is None:
458*cda5da8dSAndroid Build Coastguard Worker            return _no_type
459*cda5da8dSAndroid Build Coastguard Worker
460*cda5da8dSAndroid Build Coastguard Worker        info = doc._get_elem_info(elem)
461*cda5da8dSAndroid Build Coastguard Worker        if info is None:
462*cda5da8dSAndroid Build Coastguard Worker            return _no_type
463*cda5da8dSAndroid Build Coastguard Worker        if self.namespaceURI:
464*cda5da8dSAndroid Build Coastguard Worker            return info.getAttributeTypeNS(self.namespaceURI, self.localName)
465*cda5da8dSAndroid Build Coastguard Worker        else:
466*cda5da8dSAndroid Build Coastguard Worker            return info.getAttributeType(self.nodeName)
467*cda5da8dSAndroid Build Coastguard Worker
468*cda5da8dSAndroid Build Coastguard Workerdefproperty(Attr, "isId",       doc="True if this attribute is an ID.")
469*cda5da8dSAndroid Build Coastguard Workerdefproperty(Attr, "localName",  doc="Namespace-local name of this attribute.")
470*cda5da8dSAndroid Build Coastguard Workerdefproperty(Attr, "schemaType", doc="Schema type for this attribute.")
471*cda5da8dSAndroid Build Coastguard Worker
472*cda5da8dSAndroid Build Coastguard Worker
473*cda5da8dSAndroid Build Coastguard Workerclass NamedNodeMap(object):
474*cda5da8dSAndroid Build Coastguard Worker    """The attribute list is a transient interface to the underlying
475*cda5da8dSAndroid Build Coastguard Worker    dictionaries.  Mutations here will change the underlying element's
476*cda5da8dSAndroid Build Coastguard Worker    dictionary.
477*cda5da8dSAndroid Build Coastguard Worker
478*cda5da8dSAndroid Build Coastguard Worker    Ordering is imposed artificially and does not reflect the order of
479*cda5da8dSAndroid Build Coastguard Worker    attributes as found in an input document.
480*cda5da8dSAndroid Build Coastguard Worker    """
481*cda5da8dSAndroid Build Coastguard Worker
482*cda5da8dSAndroid Build Coastguard Worker    __slots__ = ('_attrs', '_attrsNS', '_ownerElement')
483*cda5da8dSAndroid Build Coastguard Worker
484*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, attrs, attrsNS, ownerElement):
485*cda5da8dSAndroid Build Coastguard Worker        self._attrs = attrs
486*cda5da8dSAndroid Build Coastguard Worker        self._attrsNS = attrsNS
487*cda5da8dSAndroid Build Coastguard Worker        self._ownerElement = ownerElement
488*cda5da8dSAndroid Build Coastguard Worker
489*cda5da8dSAndroid Build Coastguard Worker    def _get_length(self):
490*cda5da8dSAndroid Build Coastguard Worker        return len(self._attrs)
491*cda5da8dSAndroid Build Coastguard Worker
492*cda5da8dSAndroid Build Coastguard Worker    def item(self, index):
493*cda5da8dSAndroid Build Coastguard Worker        try:
494*cda5da8dSAndroid Build Coastguard Worker            return self[list(self._attrs.keys())[index]]
495*cda5da8dSAndroid Build Coastguard Worker        except IndexError:
496*cda5da8dSAndroid Build Coastguard Worker            return None
497*cda5da8dSAndroid Build Coastguard Worker
498*cda5da8dSAndroid Build Coastguard Worker    def items(self):
499*cda5da8dSAndroid Build Coastguard Worker        L = []
500*cda5da8dSAndroid Build Coastguard Worker        for node in self._attrs.values():
501*cda5da8dSAndroid Build Coastguard Worker            L.append((node.nodeName, node.value))
502*cda5da8dSAndroid Build Coastguard Worker        return L
503*cda5da8dSAndroid Build Coastguard Worker
504*cda5da8dSAndroid Build Coastguard Worker    def itemsNS(self):
505*cda5da8dSAndroid Build Coastguard Worker        L = []
506*cda5da8dSAndroid Build Coastguard Worker        for node in self._attrs.values():
507*cda5da8dSAndroid Build Coastguard Worker            L.append(((node.namespaceURI, node.localName), node.value))
508*cda5da8dSAndroid Build Coastguard Worker        return L
509*cda5da8dSAndroid Build Coastguard Worker
510*cda5da8dSAndroid Build Coastguard Worker    def __contains__(self, key):
511*cda5da8dSAndroid Build Coastguard Worker        if isinstance(key, str):
512*cda5da8dSAndroid Build Coastguard Worker            return key in self._attrs
513*cda5da8dSAndroid Build Coastguard Worker        else:
514*cda5da8dSAndroid Build Coastguard Worker            return key in self._attrsNS
515*cda5da8dSAndroid Build Coastguard Worker
516*cda5da8dSAndroid Build Coastguard Worker    def keys(self):
517*cda5da8dSAndroid Build Coastguard Worker        return self._attrs.keys()
518*cda5da8dSAndroid Build Coastguard Worker
519*cda5da8dSAndroid Build Coastguard Worker    def keysNS(self):
520*cda5da8dSAndroid Build Coastguard Worker        return self._attrsNS.keys()
521*cda5da8dSAndroid Build Coastguard Worker
522*cda5da8dSAndroid Build Coastguard Worker    def values(self):
523*cda5da8dSAndroid Build Coastguard Worker        return self._attrs.values()
524*cda5da8dSAndroid Build Coastguard Worker
525*cda5da8dSAndroid Build Coastguard Worker    def get(self, name, value=None):
526*cda5da8dSAndroid Build Coastguard Worker        return self._attrs.get(name, value)
527*cda5da8dSAndroid Build Coastguard Worker
528*cda5da8dSAndroid Build Coastguard Worker    __len__ = _get_length
529*cda5da8dSAndroid Build Coastguard Worker
530*cda5da8dSAndroid Build Coastguard Worker    def _cmp(self, other):
531*cda5da8dSAndroid Build Coastguard Worker        if self._attrs is getattr(other, "_attrs", None):
532*cda5da8dSAndroid Build Coastguard Worker            return 0
533*cda5da8dSAndroid Build Coastguard Worker        else:
534*cda5da8dSAndroid Build Coastguard Worker            return (id(self) > id(other)) - (id(self) < id(other))
535*cda5da8dSAndroid Build Coastguard Worker
536*cda5da8dSAndroid Build Coastguard Worker    def __eq__(self, other):
537*cda5da8dSAndroid Build Coastguard Worker        return self._cmp(other) == 0
538*cda5da8dSAndroid Build Coastguard Worker
539*cda5da8dSAndroid Build Coastguard Worker    def __ge__(self, other):
540*cda5da8dSAndroid Build Coastguard Worker        return self._cmp(other) >= 0
541*cda5da8dSAndroid Build Coastguard Worker
542*cda5da8dSAndroid Build Coastguard Worker    def __gt__(self, other):
543*cda5da8dSAndroid Build Coastguard Worker        return self._cmp(other) > 0
544*cda5da8dSAndroid Build Coastguard Worker
545*cda5da8dSAndroid Build Coastguard Worker    def __le__(self, other):
546*cda5da8dSAndroid Build Coastguard Worker        return self._cmp(other) <= 0
547*cda5da8dSAndroid Build Coastguard Worker
548*cda5da8dSAndroid Build Coastguard Worker    def __lt__(self, other):
549*cda5da8dSAndroid Build Coastguard Worker        return self._cmp(other) < 0
550*cda5da8dSAndroid Build Coastguard Worker
551*cda5da8dSAndroid Build Coastguard Worker    def __getitem__(self, attname_or_tuple):
552*cda5da8dSAndroid Build Coastguard Worker        if isinstance(attname_or_tuple, tuple):
553*cda5da8dSAndroid Build Coastguard Worker            return self._attrsNS[attname_or_tuple]
554*cda5da8dSAndroid Build Coastguard Worker        else:
555*cda5da8dSAndroid Build Coastguard Worker            return self._attrs[attname_or_tuple]
556*cda5da8dSAndroid Build Coastguard Worker
557*cda5da8dSAndroid Build Coastguard Worker    # same as set
558*cda5da8dSAndroid Build Coastguard Worker    def __setitem__(self, attname, value):
559*cda5da8dSAndroid Build Coastguard Worker        if isinstance(value, str):
560*cda5da8dSAndroid Build Coastguard Worker            try:
561*cda5da8dSAndroid Build Coastguard Worker                node = self._attrs[attname]
562*cda5da8dSAndroid Build Coastguard Worker            except KeyError:
563*cda5da8dSAndroid Build Coastguard Worker                node = Attr(attname)
564*cda5da8dSAndroid Build Coastguard Worker                node.ownerDocument = self._ownerElement.ownerDocument
565*cda5da8dSAndroid Build Coastguard Worker                self.setNamedItem(node)
566*cda5da8dSAndroid Build Coastguard Worker            node.value = value
567*cda5da8dSAndroid Build Coastguard Worker        else:
568*cda5da8dSAndroid Build Coastguard Worker            if not isinstance(value, Attr):
569*cda5da8dSAndroid Build Coastguard Worker                raise TypeError("value must be a string or Attr object")
570*cda5da8dSAndroid Build Coastguard Worker            node = value
571*cda5da8dSAndroid Build Coastguard Worker            self.setNamedItem(node)
572*cda5da8dSAndroid Build Coastguard Worker
573*cda5da8dSAndroid Build Coastguard Worker    def getNamedItem(self, name):
574*cda5da8dSAndroid Build Coastguard Worker        try:
575*cda5da8dSAndroid Build Coastguard Worker            return self._attrs[name]
576*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
577*cda5da8dSAndroid Build Coastguard Worker            return None
578*cda5da8dSAndroid Build Coastguard Worker
579*cda5da8dSAndroid Build Coastguard Worker    def getNamedItemNS(self, namespaceURI, localName):
580*cda5da8dSAndroid Build Coastguard Worker        try:
581*cda5da8dSAndroid Build Coastguard Worker            return self._attrsNS[(namespaceURI, localName)]
582*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
583*cda5da8dSAndroid Build Coastguard Worker            return None
584*cda5da8dSAndroid Build Coastguard Worker
585*cda5da8dSAndroid Build Coastguard Worker    def removeNamedItem(self, name):
586*cda5da8dSAndroid Build Coastguard Worker        n = self.getNamedItem(name)
587*cda5da8dSAndroid Build Coastguard Worker        if n is not None:
588*cda5da8dSAndroid Build Coastguard Worker            _clear_id_cache(self._ownerElement)
589*cda5da8dSAndroid Build Coastguard Worker            del self._attrs[n.nodeName]
590*cda5da8dSAndroid Build Coastguard Worker            del self._attrsNS[(n.namespaceURI, n.localName)]
591*cda5da8dSAndroid Build Coastguard Worker            if hasattr(n, 'ownerElement'):
592*cda5da8dSAndroid Build Coastguard Worker                n.ownerElement = None
593*cda5da8dSAndroid Build Coastguard Worker            return n
594*cda5da8dSAndroid Build Coastguard Worker        else:
595*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.NotFoundErr()
596*cda5da8dSAndroid Build Coastguard Worker
597*cda5da8dSAndroid Build Coastguard Worker    def removeNamedItemNS(self, namespaceURI, localName):
598*cda5da8dSAndroid Build Coastguard Worker        n = self.getNamedItemNS(namespaceURI, localName)
599*cda5da8dSAndroid Build Coastguard Worker        if n is not None:
600*cda5da8dSAndroid Build Coastguard Worker            _clear_id_cache(self._ownerElement)
601*cda5da8dSAndroid Build Coastguard Worker            del self._attrsNS[(n.namespaceURI, n.localName)]
602*cda5da8dSAndroid Build Coastguard Worker            del self._attrs[n.nodeName]
603*cda5da8dSAndroid Build Coastguard Worker            if hasattr(n, 'ownerElement'):
604*cda5da8dSAndroid Build Coastguard Worker                n.ownerElement = None
605*cda5da8dSAndroid Build Coastguard Worker            return n
606*cda5da8dSAndroid Build Coastguard Worker        else:
607*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.NotFoundErr()
608*cda5da8dSAndroid Build Coastguard Worker
609*cda5da8dSAndroid Build Coastguard Worker    def setNamedItem(self, node):
610*cda5da8dSAndroid Build Coastguard Worker        if not isinstance(node, Attr):
611*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.HierarchyRequestErr(
612*cda5da8dSAndroid Build Coastguard Worker                "%s cannot be child of %s" % (repr(node), repr(self)))
613*cda5da8dSAndroid Build Coastguard Worker        old = self._attrs.get(node.name)
614*cda5da8dSAndroid Build Coastguard Worker        if old:
615*cda5da8dSAndroid Build Coastguard Worker            old.unlink()
616*cda5da8dSAndroid Build Coastguard Worker        self._attrs[node.name] = node
617*cda5da8dSAndroid Build Coastguard Worker        self._attrsNS[(node.namespaceURI, node.localName)] = node
618*cda5da8dSAndroid Build Coastguard Worker        node.ownerElement = self._ownerElement
619*cda5da8dSAndroid Build Coastguard Worker        _clear_id_cache(node.ownerElement)
620*cda5da8dSAndroid Build Coastguard Worker        return old
621*cda5da8dSAndroid Build Coastguard Worker
622*cda5da8dSAndroid Build Coastguard Worker    def setNamedItemNS(self, node):
623*cda5da8dSAndroid Build Coastguard Worker        return self.setNamedItem(node)
624*cda5da8dSAndroid Build Coastguard Worker
625*cda5da8dSAndroid Build Coastguard Worker    def __delitem__(self, attname_or_tuple):
626*cda5da8dSAndroid Build Coastguard Worker        node = self[attname_or_tuple]
627*cda5da8dSAndroid Build Coastguard Worker        _clear_id_cache(node.ownerElement)
628*cda5da8dSAndroid Build Coastguard Worker        node.unlink()
629*cda5da8dSAndroid Build Coastguard Worker
630*cda5da8dSAndroid Build Coastguard Worker    def __getstate__(self):
631*cda5da8dSAndroid Build Coastguard Worker        return self._attrs, self._attrsNS, self._ownerElement
632*cda5da8dSAndroid Build Coastguard Worker
633*cda5da8dSAndroid Build Coastguard Worker    def __setstate__(self, state):
634*cda5da8dSAndroid Build Coastguard Worker        self._attrs, self._attrsNS, self._ownerElement = state
635*cda5da8dSAndroid Build Coastguard Worker
636*cda5da8dSAndroid Build Coastguard Workerdefproperty(NamedNodeMap, "length",
637*cda5da8dSAndroid Build Coastguard Worker            doc="Number of nodes in the NamedNodeMap.")
638*cda5da8dSAndroid Build Coastguard Worker
639*cda5da8dSAndroid Build Coastguard WorkerAttributeList = NamedNodeMap
640*cda5da8dSAndroid Build Coastguard Worker
641*cda5da8dSAndroid Build Coastguard Worker
642*cda5da8dSAndroid Build Coastguard Workerclass TypeInfo(object):
643*cda5da8dSAndroid Build Coastguard Worker    __slots__ = 'namespace', 'name'
644*cda5da8dSAndroid Build Coastguard Worker
645*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, namespace, name):
646*cda5da8dSAndroid Build Coastguard Worker        self.namespace = namespace
647*cda5da8dSAndroid Build Coastguard Worker        self.name = name
648*cda5da8dSAndroid Build Coastguard Worker
649*cda5da8dSAndroid Build Coastguard Worker    def __repr__(self):
650*cda5da8dSAndroid Build Coastguard Worker        if self.namespace:
651*cda5da8dSAndroid Build Coastguard Worker            return "<%s %r (from %r)>" % (self.__class__.__name__, self.name,
652*cda5da8dSAndroid Build Coastguard Worker                                          self.namespace)
653*cda5da8dSAndroid Build Coastguard Worker        else:
654*cda5da8dSAndroid Build Coastguard Worker            return "<%s %r>" % (self.__class__.__name__, self.name)
655*cda5da8dSAndroid Build Coastguard Worker
656*cda5da8dSAndroid Build Coastguard Worker    def _get_name(self):
657*cda5da8dSAndroid Build Coastguard Worker        return self.name
658*cda5da8dSAndroid Build Coastguard Worker
659*cda5da8dSAndroid Build Coastguard Worker    def _get_namespace(self):
660*cda5da8dSAndroid Build Coastguard Worker        return self.namespace
661*cda5da8dSAndroid Build Coastguard Worker
662*cda5da8dSAndroid Build Coastguard Worker_no_type = TypeInfo(None, None)
663*cda5da8dSAndroid Build Coastguard Worker
664*cda5da8dSAndroid Build Coastguard Workerclass Element(Node):
665*cda5da8dSAndroid Build Coastguard Worker    __slots__=('ownerDocument', 'parentNode', 'tagName', 'nodeName', 'prefix',
666*cda5da8dSAndroid Build Coastguard Worker               'namespaceURI', '_localName', 'childNodes', '_attrs', '_attrsNS',
667*cda5da8dSAndroid Build Coastguard Worker               'nextSibling', 'previousSibling')
668*cda5da8dSAndroid Build Coastguard Worker    nodeType = Node.ELEMENT_NODE
669*cda5da8dSAndroid Build Coastguard Worker    nodeValue = None
670*cda5da8dSAndroid Build Coastguard Worker    schemaType = _no_type
671*cda5da8dSAndroid Build Coastguard Worker
672*cda5da8dSAndroid Build Coastguard Worker    _magic_id_nodes = 0
673*cda5da8dSAndroid Build Coastguard Worker
674*cda5da8dSAndroid Build Coastguard Worker    _child_node_types = (Node.ELEMENT_NODE,
675*cda5da8dSAndroid Build Coastguard Worker                         Node.PROCESSING_INSTRUCTION_NODE,
676*cda5da8dSAndroid Build Coastguard Worker                         Node.COMMENT_NODE,
677*cda5da8dSAndroid Build Coastguard Worker                         Node.TEXT_NODE,
678*cda5da8dSAndroid Build Coastguard Worker                         Node.CDATA_SECTION_NODE,
679*cda5da8dSAndroid Build Coastguard Worker                         Node.ENTITY_REFERENCE_NODE)
680*cda5da8dSAndroid Build Coastguard Worker
681*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, tagName, namespaceURI=EMPTY_NAMESPACE, prefix=None,
682*cda5da8dSAndroid Build Coastguard Worker                 localName=None):
683*cda5da8dSAndroid Build Coastguard Worker        self.parentNode = None
684*cda5da8dSAndroid Build Coastguard Worker        self.tagName = self.nodeName = tagName
685*cda5da8dSAndroid Build Coastguard Worker        self.prefix = prefix
686*cda5da8dSAndroid Build Coastguard Worker        self.namespaceURI = namespaceURI
687*cda5da8dSAndroid Build Coastguard Worker        self.childNodes = NodeList()
688*cda5da8dSAndroid Build Coastguard Worker        self.nextSibling = self.previousSibling = None
689*cda5da8dSAndroid Build Coastguard Worker
690*cda5da8dSAndroid Build Coastguard Worker        # Attribute dictionaries are lazily created
691*cda5da8dSAndroid Build Coastguard Worker        # attributes are double-indexed:
692*cda5da8dSAndroid Build Coastguard Worker        #    tagName -> Attribute
693*cda5da8dSAndroid Build Coastguard Worker        #    URI,localName -> Attribute
694*cda5da8dSAndroid Build Coastguard Worker        # in the future: consider lazy generation
695*cda5da8dSAndroid Build Coastguard Worker        # of attribute objects this is too tricky
696*cda5da8dSAndroid Build Coastguard Worker        # for now because of headaches with
697*cda5da8dSAndroid Build Coastguard Worker        # namespaces.
698*cda5da8dSAndroid Build Coastguard Worker        self._attrs = None
699*cda5da8dSAndroid Build Coastguard Worker        self._attrsNS = None
700*cda5da8dSAndroid Build Coastguard Worker
701*cda5da8dSAndroid Build Coastguard Worker    def _ensure_attributes(self):
702*cda5da8dSAndroid Build Coastguard Worker        if self._attrs is None:
703*cda5da8dSAndroid Build Coastguard Worker            self._attrs = {}
704*cda5da8dSAndroid Build Coastguard Worker            self._attrsNS = {}
705*cda5da8dSAndroid Build Coastguard Worker
706*cda5da8dSAndroid Build Coastguard Worker    def _get_localName(self):
707*cda5da8dSAndroid Build Coastguard Worker        try:
708*cda5da8dSAndroid Build Coastguard Worker            return self._localName
709*cda5da8dSAndroid Build Coastguard Worker        except AttributeError:
710*cda5da8dSAndroid Build Coastguard Worker            return self.tagName.split(":", 1)[-1]
711*cda5da8dSAndroid Build Coastguard Worker
712*cda5da8dSAndroid Build Coastguard Worker    def _get_tagName(self):
713*cda5da8dSAndroid Build Coastguard Worker        return self.tagName
714*cda5da8dSAndroid Build Coastguard Worker
715*cda5da8dSAndroid Build Coastguard Worker    def unlink(self):
716*cda5da8dSAndroid Build Coastguard Worker        if self._attrs is not None:
717*cda5da8dSAndroid Build Coastguard Worker            for attr in list(self._attrs.values()):
718*cda5da8dSAndroid Build Coastguard Worker                attr.unlink()
719*cda5da8dSAndroid Build Coastguard Worker        self._attrs = None
720*cda5da8dSAndroid Build Coastguard Worker        self._attrsNS = None
721*cda5da8dSAndroid Build Coastguard Worker        Node.unlink(self)
722*cda5da8dSAndroid Build Coastguard Worker
723*cda5da8dSAndroid Build Coastguard Worker    def getAttribute(self, attname):
724*cda5da8dSAndroid Build Coastguard Worker        """Returns the value of the specified attribute.
725*cda5da8dSAndroid Build Coastguard Worker
726*cda5da8dSAndroid Build Coastguard Worker        Returns the value of the element's attribute named attname as
727*cda5da8dSAndroid Build Coastguard Worker        a string. An empty string is returned if the element does not
728*cda5da8dSAndroid Build Coastguard Worker        have such an attribute. Note that an empty string may also be
729*cda5da8dSAndroid Build Coastguard Worker        returned as an explicitly given attribute value, use the
730*cda5da8dSAndroid Build Coastguard Worker        hasAttribute method to distinguish these two cases.
731*cda5da8dSAndroid Build Coastguard Worker        """
732*cda5da8dSAndroid Build Coastguard Worker        if self._attrs is None:
733*cda5da8dSAndroid Build Coastguard Worker            return ""
734*cda5da8dSAndroid Build Coastguard Worker        try:
735*cda5da8dSAndroid Build Coastguard Worker            return self._attrs[attname].value
736*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
737*cda5da8dSAndroid Build Coastguard Worker            return ""
738*cda5da8dSAndroid Build Coastguard Worker
739*cda5da8dSAndroid Build Coastguard Worker    def getAttributeNS(self, namespaceURI, localName):
740*cda5da8dSAndroid Build Coastguard Worker        if self._attrsNS is None:
741*cda5da8dSAndroid Build Coastguard Worker            return ""
742*cda5da8dSAndroid Build Coastguard Worker        try:
743*cda5da8dSAndroid Build Coastguard Worker            return self._attrsNS[(namespaceURI, localName)].value
744*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
745*cda5da8dSAndroid Build Coastguard Worker            return ""
746*cda5da8dSAndroid Build Coastguard Worker
747*cda5da8dSAndroid Build Coastguard Worker    def setAttribute(self, attname, value):
748*cda5da8dSAndroid Build Coastguard Worker        attr = self.getAttributeNode(attname)
749*cda5da8dSAndroid Build Coastguard Worker        if attr is None:
750*cda5da8dSAndroid Build Coastguard Worker            attr = Attr(attname)
751*cda5da8dSAndroid Build Coastguard Worker            attr.value = value # also sets nodeValue
752*cda5da8dSAndroid Build Coastguard Worker            attr.ownerDocument = self.ownerDocument
753*cda5da8dSAndroid Build Coastguard Worker            self.setAttributeNode(attr)
754*cda5da8dSAndroid Build Coastguard Worker        elif value != attr.value:
755*cda5da8dSAndroid Build Coastguard Worker            attr.value = value
756*cda5da8dSAndroid Build Coastguard Worker            if attr.isId:
757*cda5da8dSAndroid Build Coastguard Worker                _clear_id_cache(self)
758*cda5da8dSAndroid Build Coastguard Worker
759*cda5da8dSAndroid Build Coastguard Worker    def setAttributeNS(self, namespaceURI, qualifiedName, value):
760*cda5da8dSAndroid Build Coastguard Worker        prefix, localname = _nssplit(qualifiedName)
761*cda5da8dSAndroid Build Coastguard Worker        attr = self.getAttributeNodeNS(namespaceURI, localname)
762*cda5da8dSAndroid Build Coastguard Worker        if attr is None:
763*cda5da8dSAndroid Build Coastguard Worker            attr = Attr(qualifiedName, namespaceURI, localname, prefix)
764*cda5da8dSAndroid Build Coastguard Worker            attr.value = value
765*cda5da8dSAndroid Build Coastguard Worker            attr.ownerDocument = self.ownerDocument
766*cda5da8dSAndroid Build Coastguard Worker            self.setAttributeNode(attr)
767*cda5da8dSAndroid Build Coastguard Worker        else:
768*cda5da8dSAndroid Build Coastguard Worker            if value != attr.value:
769*cda5da8dSAndroid Build Coastguard Worker                attr.value = value
770*cda5da8dSAndroid Build Coastguard Worker                if attr.isId:
771*cda5da8dSAndroid Build Coastguard Worker                    _clear_id_cache(self)
772*cda5da8dSAndroid Build Coastguard Worker            if attr.prefix != prefix:
773*cda5da8dSAndroid Build Coastguard Worker                attr.prefix = prefix
774*cda5da8dSAndroid Build Coastguard Worker                attr.nodeName = qualifiedName
775*cda5da8dSAndroid Build Coastguard Worker
776*cda5da8dSAndroid Build Coastguard Worker    def getAttributeNode(self, attrname):
777*cda5da8dSAndroid Build Coastguard Worker        if self._attrs is None:
778*cda5da8dSAndroid Build Coastguard Worker            return None
779*cda5da8dSAndroid Build Coastguard Worker        return self._attrs.get(attrname)
780*cda5da8dSAndroid Build Coastguard Worker
781*cda5da8dSAndroid Build Coastguard Worker    def getAttributeNodeNS(self, namespaceURI, localName):
782*cda5da8dSAndroid Build Coastguard Worker        if self._attrsNS is None:
783*cda5da8dSAndroid Build Coastguard Worker            return None
784*cda5da8dSAndroid Build Coastguard Worker        return self._attrsNS.get((namespaceURI, localName))
785*cda5da8dSAndroid Build Coastguard Worker
786*cda5da8dSAndroid Build Coastguard Worker    def setAttributeNode(self, attr):
787*cda5da8dSAndroid Build Coastguard Worker        if attr.ownerElement not in (None, self):
788*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.InuseAttributeErr("attribute node already owned")
789*cda5da8dSAndroid Build Coastguard Worker        self._ensure_attributes()
790*cda5da8dSAndroid Build Coastguard Worker        old1 = self._attrs.get(attr.name, None)
791*cda5da8dSAndroid Build Coastguard Worker        if old1 is not None:
792*cda5da8dSAndroid Build Coastguard Worker            self.removeAttributeNode(old1)
793*cda5da8dSAndroid Build Coastguard Worker        old2 = self._attrsNS.get((attr.namespaceURI, attr.localName), None)
794*cda5da8dSAndroid Build Coastguard Worker        if old2 is not None and old2 is not old1:
795*cda5da8dSAndroid Build Coastguard Worker            self.removeAttributeNode(old2)
796*cda5da8dSAndroid Build Coastguard Worker        _set_attribute_node(self, attr)
797*cda5da8dSAndroid Build Coastguard Worker
798*cda5da8dSAndroid Build Coastguard Worker        if old1 is not attr:
799*cda5da8dSAndroid Build Coastguard Worker            # It might have already been part of this node, in which case
800*cda5da8dSAndroid Build Coastguard Worker            # it doesn't represent a change, and should not be returned.
801*cda5da8dSAndroid Build Coastguard Worker            return old1
802*cda5da8dSAndroid Build Coastguard Worker        if old2 is not attr:
803*cda5da8dSAndroid Build Coastguard Worker            return old2
804*cda5da8dSAndroid Build Coastguard Worker
805*cda5da8dSAndroid Build Coastguard Worker    setAttributeNodeNS = setAttributeNode
806*cda5da8dSAndroid Build Coastguard Worker
807*cda5da8dSAndroid Build Coastguard Worker    def removeAttribute(self, name):
808*cda5da8dSAndroid Build Coastguard Worker        if self._attrsNS is None:
809*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.NotFoundErr()
810*cda5da8dSAndroid Build Coastguard Worker        try:
811*cda5da8dSAndroid Build Coastguard Worker            attr = self._attrs[name]
812*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
813*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.NotFoundErr()
814*cda5da8dSAndroid Build Coastguard Worker        self.removeAttributeNode(attr)
815*cda5da8dSAndroid Build Coastguard Worker
816*cda5da8dSAndroid Build Coastguard Worker    def removeAttributeNS(self, namespaceURI, localName):
817*cda5da8dSAndroid Build Coastguard Worker        if self._attrsNS is None:
818*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.NotFoundErr()
819*cda5da8dSAndroid Build Coastguard Worker        try:
820*cda5da8dSAndroid Build Coastguard Worker            attr = self._attrsNS[(namespaceURI, localName)]
821*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
822*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.NotFoundErr()
823*cda5da8dSAndroid Build Coastguard Worker        self.removeAttributeNode(attr)
824*cda5da8dSAndroid Build Coastguard Worker
825*cda5da8dSAndroid Build Coastguard Worker    def removeAttributeNode(self, node):
826*cda5da8dSAndroid Build Coastguard Worker        if node is None:
827*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.NotFoundErr()
828*cda5da8dSAndroid Build Coastguard Worker        try:
829*cda5da8dSAndroid Build Coastguard Worker            self._attrs[node.name]
830*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
831*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.NotFoundErr()
832*cda5da8dSAndroid Build Coastguard Worker        _clear_id_cache(self)
833*cda5da8dSAndroid Build Coastguard Worker        node.unlink()
834*cda5da8dSAndroid Build Coastguard Worker        # Restore this since the node is still useful and otherwise
835*cda5da8dSAndroid Build Coastguard Worker        # unlinked
836*cda5da8dSAndroid Build Coastguard Worker        node.ownerDocument = self.ownerDocument
837*cda5da8dSAndroid Build Coastguard Worker        return node
838*cda5da8dSAndroid Build Coastguard Worker
839*cda5da8dSAndroid Build Coastguard Worker    removeAttributeNodeNS = removeAttributeNode
840*cda5da8dSAndroid Build Coastguard Worker
841*cda5da8dSAndroid Build Coastguard Worker    def hasAttribute(self, name):
842*cda5da8dSAndroid Build Coastguard Worker        """Checks whether the element has an attribute with the specified name.
843*cda5da8dSAndroid Build Coastguard Worker
844*cda5da8dSAndroid Build Coastguard Worker        Returns True if the element has an attribute with the specified name.
845*cda5da8dSAndroid Build Coastguard Worker        Otherwise, returns False.
846*cda5da8dSAndroid Build Coastguard Worker        """
847*cda5da8dSAndroid Build Coastguard Worker        if self._attrs is None:
848*cda5da8dSAndroid Build Coastguard Worker            return False
849*cda5da8dSAndroid Build Coastguard Worker        return name in self._attrs
850*cda5da8dSAndroid Build Coastguard Worker
851*cda5da8dSAndroid Build Coastguard Worker    def hasAttributeNS(self, namespaceURI, localName):
852*cda5da8dSAndroid Build Coastguard Worker        if self._attrsNS is None:
853*cda5da8dSAndroid Build Coastguard Worker            return False
854*cda5da8dSAndroid Build Coastguard Worker        return (namespaceURI, localName) in self._attrsNS
855*cda5da8dSAndroid Build Coastguard Worker
856*cda5da8dSAndroid Build Coastguard Worker    def getElementsByTagName(self, name):
857*cda5da8dSAndroid Build Coastguard Worker        """Returns all descendant elements with the given tag name.
858*cda5da8dSAndroid Build Coastguard Worker
859*cda5da8dSAndroid Build Coastguard Worker        Returns the list of all descendant elements (not direct children
860*cda5da8dSAndroid Build Coastguard Worker        only) with the specified tag name.
861*cda5da8dSAndroid Build Coastguard Worker        """
862*cda5da8dSAndroid Build Coastguard Worker        return _get_elements_by_tagName_helper(self, name, NodeList())
863*cda5da8dSAndroid Build Coastguard Worker
864*cda5da8dSAndroid Build Coastguard Worker    def getElementsByTagNameNS(self, namespaceURI, localName):
865*cda5da8dSAndroid Build Coastguard Worker        return _get_elements_by_tagName_ns_helper(
866*cda5da8dSAndroid Build Coastguard Worker            self, namespaceURI, localName, NodeList())
867*cda5da8dSAndroid Build Coastguard Worker
868*cda5da8dSAndroid Build Coastguard Worker    def __repr__(self):
869*cda5da8dSAndroid Build Coastguard Worker        return "<DOM Element: %s at %#x>" % (self.tagName, id(self))
870*cda5da8dSAndroid Build Coastguard Worker
871*cda5da8dSAndroid Build Coastguard Worker    def writexml(self, writer, indent="", addindent="", newl=""):
872*cda5da8dSAndroid Build Coastguard Worker        """Write an XML element to a file-like object
873*cda5da8dSAndroid Build Coastguard Worker
874*cda5da8dSAndroid Build Coastguard Worker        Write the element to the writer object that must provide
875*cda5da8dSAndroid Build Coastguard Worker        a write method (e.g. a file or StringIO object).
876*cda5da8dSAndroid Build Coastguard Worker        """
877*cda5da8dSAndroid Build Coastguard Worker        # indent = current indentation
878*cda5da8dSAndroid Build Coastguard Worker        # addindent = indentation to add to higher levels
879*cda5da8dSAndroid Build Coastguard Worker        # newl = newline string
880*cda5da8dSAndroid Build Coastguard Worker        writer.write(indent+"<" + self.tagName)
881*cda5da8dSAndroid Build Coastguard Worker
882*cda5da8dSAndroid Build Coastguard Worker        attrs = self._get_attributes()
883*cda5da8dSAndroid Build Coastguard Worker
884*cda5da8dSAndroid Build Coastguard Worker        for a_name in attrs.keys():
885*cda5da8dSAndroid Build Coastguard Worker            writer.write(" %s=\"" % a_name)
886*cda5da8dSAndroid Build Coastguard Worker            _write_data(writer, attrs[a_name].value)
887*cda5da8dSAndroid Build Coastguard Worker            writer.write("\"")
888*cda5da8dSAndroid Build Coastguard Worker        if self.childNodes:
889*cda5da8dSAndroid Build Coastguard Worker            writer.write(">")
890*cda5da8dSAndroid Build Coastguard Worker            if (len(self.childNodes) == 1 and
891*cda5da8dSAndroid Build Coastguard Worker                self.childNodes[0].nodeType in (
892*cda5da8dSAndroid Build Coastguard Worker                        Node.TEXT_NODE, Node.CDATA_SECTION_NODE)):
893*cda5da8dSAndroid Build Coastguard Worker                self.childNodes[0].writexml(writer, '', '', '')
894*cda5da8dSAndroid Build Coastguard Worker            else:
895*cda5da8dSAndroid Build Coastguard Worker                writer.write(newl)
896*cda5da8dSAndroid Build Coastguard Worker                for node in self.childNodes:
897*cda5da8dSAndroid Build Coastguard Worker                    node.writexml(writer, indent+addindent, addindent, newl)
898*cda5da8dSAndroid Build Coastguard Worker                writer.write(indent)
899*cda5da8dSAndroid Build Coastguard Worker            writer.write("</%s>%s" % (self.tagName, newl))
900*cda5da8dSAndroid Build Coastguard Worker        else:
901*cda5da8dSAndroid Build Coastguard Worker            writer.write("/>%s"%(newl))
902*cda5da8dSAndroid Build Coastguard Worker
903*cda5da8dSAndroid Build Coastguard Worker    def _get_attributes(self):
904*cda5da8dSAndroid Build Coastguard Worker        self._ensure_attributes()
905*cda5da8dSAndroid Build Coastguard Worker        return NamedNodeMap(self._attrs, self._attrsNS, self)
906*cda5da8dSAndroid Build Coastguard Worker
907*cda5da8dSAndroid Build Coastguard Worker    def hasAttributes(self):
908*cda5da8dSAndroid Build Coastguard Worker        if self._attrs:
909*cda5da8dSAndroid Build Coastguard Worker            return True
910*cda5da8dSAndroid Build Coastguard Worker        else:
911*cda5da8dSAndroid Build Coastguard Worker            return False
912*cda5da8dSAndroid Build Coastguard Worker
913*cda5da8dSAndroid Build Coastguard Worker    # DOM Level 3 attributes, based on the 22 Oct 2002 draft
914*cda5da8dSAndroid Build Coastguard Worker
915*cda5da8dSAndroid Build Coastguard Worker    def setIdAttribute(self, name):
916*cda5da8dSAndroid Build Coastguard Worker        idAttr = self.getAttributeNode(name)
917*cda5da8dSAndroid Build Coastguard Worker        self.setIdAttributeNode(idAttr)
918*cda5da8dSAndroid Build Coastguard Worker
919*cda5da8dSAndroid Build Coastguard Worker    def setIdAttributeNS(self, namespaceURI, localName):
920*cda5da8dSAndroid Build Coastguard Worker        idAttr = self.getAttributeNodeNS(namespaceURI, localName)
921*cda5da8dSAndroid Build Coastguard Worker        self.setIdAttributeNode(idAttr)
922*cda5da8dSAndroid Build Coastguard Worker
923*cda5da8dSAndroid Build Coastguard Worker    def setIdAttributeNode(self, idAttr):
924*cda5da8dSAndroid Build Coastguard Worker        if idAttr is None or not self.isSameNode(idAttr.ownerElement):
925*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.NotFoundErr()
926*cda5da8dSAndroid Build Coastguard Worker        if _get_containing_entref(self) is not None:
927*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.NoModificationAllowedErr()
928*cda5da8dSAndroid Build Coastguard Worker        if not idAttr._is_id:
929*cda5da8dSAndroid Build Coastguard Worker            idAttr._is_id = True
930*cda5da8dSAndroid Build Coastguard Worker            self._magic_id_nodes += 1
931*cda5da8dSAndroid Build Coastguard Worker            self.ownerDocument._magic_id_count += 1
932*cda5da8dSAndroid Build Coastguard Worker            _clear_id_cache(self)
933*cda5da8dSAndroid Build Coastguard Worker
934*cda5da8dSAndroid Build Coastguard Workerdefproperty(Element, "attributes",
935*cda5da8dSAndroid Build Coastguard Worker            doc="NamedNodeMap of attributes on the element.")
936*cda5da8dSAndroid Build Coastguard Workerdefproperty(Element, "localName",
937*cda5da8dSAndroid Build Coastguard Worker            doc="Namespace-local name of this element.")
938*cda5da8dSAndroid Build Coastguard Worker
939*cda5da8dSAndroid Build Coastguard Worker
940*cda5da8dSAndroid Build Coastguard Workerdef _set_attribute_node(element, attr):
941*cda5da8dSAndroid Build Coastguard Worker    _clear_id_cache(element)
942*cda5da8dSAndroid Build Coastguard Worker    element._ensure_attributes()
943*cda5da8dSAndroid Build Coastguard Worker    element._attrs[attr.name] = attr
944*cda5da8dSAndroid Build Coastguard Worker    element._attrsNS[(attr.namespaceURI, attr.localName)] = attr
945*cda5da8dSAndroid Build Coastguard Worker
946*cda5da8dSAndroid Build Coastguard Worker    # This creates a circular reference, but Element.unlink()
947*cda5da8dSAndroid Build Coastguard Worker    # breaks the cycle since the references to the attribute
948*cda5da8dSAndroid Build Coastguard Worker    # dictionaries are tossed.
949*cda5da8dSAndroid Build Coastguard Worker    attr.ownerElement = element
950*cda5da8dSAndroid Build Coastguard Worker
951*cda5da8dSAndroid Build Coastguard Workerclass Childless:
952*cda5da8dSAndroid Build Coastguard Worker    """Mixin that makes childless-ness easy to implement and avoids
953*cda5da8dSAndroid Build Coastguard Worker    the complexity of the Node methods that deal with children.
954*cda5da8dSAndroid Build Coastguard Worker    """
955*cda5da8dSAndroid Build Coastguard Worker    __slots__ = ()
956*cda5da8dSAndroid Build Coastguard Worker
957*cda5da8dSAndroid Build Coastguard Worker    attributes = None
958*cda5da8dSAndroid Build Coastguard Worker    childNodes = EmptyNodeList()
959*cda5da8dSAndroid Build Coastguard Worker    firstChild = None
960*cda5da8dSAndroid Build Coastguard Worker    lastChild = None
961*cda5da8dSAndroid Build Coastguard Worker
962*cda5da8dSAndroid Build Coastguard Worker    def _get_firstChild(self):
963*cda5da8dSAndroid Build Coastguard Worker        return None
964*cda5da8dSAndroid Build Coastguard Worker
965*cda5da8dSAndroid Build Coastguard Worker    def _get_lastChild(self):
966*cda5da8dSAndroid Build Coastguard Worker        return None
967*cda5da8dSAndroid Build Coastguard Worker
968*cda5da8dSAndroid Build Coastguard Worker    def appendChild(self, node):
969*cda5da8dSAndroid Build Coastguard Worker        raise xml.dom.HierarchyRequestErr(
970*cda5da8dSAndroid Build Coastguard Worker            self.nodeName + " nodes cannot have children")
971*cda5da8dSAndroid Build Coastguard Worker
972*cda5da8dSAndroid Build Coastguard Worker    def hasChildNodes(self):
973*cda5da8dSAndroid Build Coastguard Worker        return False
974*cda5da8dSAndroid Build Coastguard Worker
975*cda5da8dSAndroid Build Coastguard Worker    def insertBefore(self, newChild, refChild):
976*cda5da8dSAndroid Build Coastguard Worker        raise xml.dom.HierarchyRequestErr(
977*cda5da8dSAndroid Build Coastguard Worker            self.nodeName + " nodes do not have children")
978*cda5da8dSAndroid Build Coastguard Worker
979*cda5da8dSAndroid Build Coastguard Worker    def removeChild(self, oldChild):
980*cda5da8dSAndroid Build Coastguard Worker        raise xml.dom.NotFoundErr(
981*cda5da8dSAndroid Build Coastguard Worker            self.nodeName + " nodes do not have children")
982*cda5da8dSAndroid Build Coastguard Worker
983*cda5da8dSAndroid Build Coastguard Worker    def normalize(self):
984*cda5da8dSAndroid Build Coastguard Worker        # For childless nodes, normalize() has nothing to do.
985*cda5da8dSAndroid Build Coastguard Worker        pass
986*cda5da8dSAndroid Build Coastguard Worker
987*cda5da8dSAndroid Build Coastguard Worker    def replaceChild(self, newChild, oldChild):
988*cda5da8dSAndroid Build Coastguard Worker        raise xml.dom.HierarchyRequestErr(
989*cda5da8dSAndroid Build Coastguard Worker            self.nodeName + " nodes do not have children")
990*cda5da8dSAndroid Build Coastguard Worker
991*cda5da8dSAndroid Build Coastguard Worker
992*cda5da8dSAndroid Build Coastguard Workerclass ProcessingInstruction(Childless, Node):
993*cda5da8dSAndroid Build Coastguard Worker    nodeType = Node.PROCESSING_INSTRUCTION_NODE
994*cda5da8dSAndroid Build Coastguard Worker    __slots__ = ('target', 'data')
995*cda5da8dSAndroid Build Coastguard Worker
996*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, target, data):
997*cda5da8dSAndroid Build Coastguard Worker        self.target = target
998*cda5da8dSAndroid Build Coastguard Worker        self.data = data
999*cda5da8dSAndroid Build Coastguard Worker
1000*cda5da8dSAndroid Build Coastguard Worker    # nodeValue is an alias for data
1001*cda5da8dSAndroid Build Coastguard Worker    def _get_nodeValue(self):
1002*cda5da8dSAndroid Build Coastguard Worker        return self.data
1003*cda5da8dSAndroid Build Coastguard Worker    def _set_nodeValue(self, value):
1004*cda5da8dSAndroid Build Coastguard Worker        self.data = value
1005*cda5da8dSAndroid Build Coastguard Worker    nodeValue = property(_get_nodeValue, _set_nodeValue)
1006*cda5da8dSAndroid Build Coastguard Worker
1007*cda5da8dSAndroid Build Coastguard Worker    # nodeName is an alias for target
1008*cda5da8dSAndroid Build Coastguard Worker    def _get_nodeName(self):
1009*cda5da8dSAndroid Build Coastguard Worker        return self.target
1010*cda5da8dSAndroid Build Coastguard Worker    def _set_nodeName(self, value):
1011*cda5da8dSAndroid Build Coastguard Worker        self.target = value
1012*cda5da8dSAndroid Build Coastguard Worker    nodeName = property(_get_nodeName, _set_nodeName)
1013*cda5da8dSAndroid Build Coastguard Worker
1014*cda5da8dSAndroid Build Coastguard Worker    def writexml(self, writer, indent="", addindent="", newl=""):
1015*cda5da8dSAndroid Build Coastguard Worker        writer.write("%s<?%s %s?>%s" % (indent,self.target, self.data, newl))
1016*cda5da8dSAndroid Build Coastguard Worker
1017*cda5da8dSAndroid Build Coastguard Worker
1018*cda5da8dSAndroid Build Coastguard Workerclass CharacterData(Childless, Node):
1019*cda5da8dSAndroid Build Coastguard Worker    __slots__=('_data', 'ownerDocument','parentNode', 'previousSibling', 'nextSibling')
1020*cda5da8dSAndroid Build Coastguard Worker
1021*cda5da8dSAndroid Build Coastguard Worker    def __init__(self):
1022*cda5da8dSAndroid Build Coastguard Worker        self.ownerDocument = self.parentNode = None
1023*cda5da8dSAndroid Build Coastguard Worker        self.previousSibling = self.nextSibling = None
1024*cda5da8dSAndroid Build Coastguard Worker        self._data = ''
1025*cda5da8dSAndroid Build Coastguard Worker        Node.__init__(self)
1026*cda5da8dSAndroid Build Coastguard Worker
1027*cda5da8dSAndroid Build Coastguard Worker    def _get_length(self):
1028*cda5da8dSAndroid Build Coastguard Worker        return len(self.data)
1029*cda5da8dSAndroid Build Coastguard Worker    __len__ = _get_length
1030*cda5da8dSAndroid Build Coastguard Worker
1031*cda5da8dSAndroid Build Coastguard Worker    def _get_data(self):
1032*cda5da8dSAndroid Build Coastguard Worker        return self._data
1033*cda5da8dSAndroid Build Coastguard Worker    def _set_data(self, data):
1034*cda5da8dSAndroid Build Coastguard Worker        self._data = data
1035*cda5da8dSAndroid Build Coastguard Worker
1036*cda5da8dSAndroid Build Coastguard Worker    data = nodeValue = property(_get_data, _set_data)
1037*cda5da8dSAndroid Build Coastguard Worker
1038*cda5da8dSAndroid Build Coastguard Worker    def __repr__(self):
1039*cda5da8dSAndroid Build Coastguard Worker        data = self.data
1040*cda5da8dSAndroid Build Coastguard Worker        if len(data) > 10:
1041*cda5da8dSAndroid Build Coastguard Worker            dotdotdot = "..."
1042*cda5da8dSAndroid Build Coastguard Worker        else:
1043*cda5da8dSAndroid Build Coastguard Worker            dotdotdot = ""
1044*cda5da8dSAndroid Build Coastguard Worker        return '<DOM %s node "%r%s">' % (
1045*cda5da8dSAndroid Build Coastguard Worker            self.__class__.__name__, data[0:10], dotdotdot)
1046*cda5da8dSAndroid Build Coastguard Worker
1047*cda5da8dSAndroid Build Coastguard Worker    def substringData(self, offset, count):
1048*cda5da8dSAndroid Build Coastguard Worker        if offset < 0:
1049*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.IndexSizeErr("offset cannot be negative")
1050*cda5da8dSAndroid Build Coastguard Worker        if offset >= len(self.data):
1051*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
1052*cda5da8dSAndroid Build Coastguard Worker        if count < 0:
1053*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.IndexSizeErr("count cannot be negative")
1054*cda5da8dSAndroid Build Coastguard Worker        return self.data[offset:offset+count]
1055*cda5da8dSAndroid Build Coastguard Worker
1056*cda5da8dSAndroid Build Coastguard Worker    def appendData(self, arg):
1057*cda5da8dSAndroid Build Coastguard Worker        self.data = self.data + arg
1058*cda5da8dSAndroid Build Coastguard Worker
1059*cda5da8dSAndroid Build Coastguard Worker    def insertData(self, offset, arg):
1060*cda5da8dSAndroid Build Coastguard Worker        if offset < 0:
1061*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.IndexSizeErr("offset cannot be negative")
1062*cda5da8dSAndroid Build Coastguard Worker        if offset >= len(self.data):
1063*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
1064*cda5da8dSAndroid Build Coastguard Worker        if arg:
1065*cda5da8dSAndroid Build Coastguard Worker            self.data = "%s%s%s" % (
1066*cda5da8dSAndroid Build Coastguard Worker                self.data[:offset], arg, self.data[offset:])
1067*cda5da8dSAndroid Build Coastguard Worker
1068*cda5da8dSAndroid Build Coastguard Worker    def deleteData(self, offset, count):
1069*cda5da8dSAndroid Build Coastguard Worker        if offset < 0:
1070*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.IndexSizeErr("offset cannot be negative")
1071*cda5da8dSAndroid Build Coastguard Worker        if offset >= len(self.data):
1072*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
1073*cda5da8dSAndroid Build Coastguard Worker        if count < 0:
1074*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.IndexSizeErr("count cannot be negative")
1075*cda5da8dSAndroid Build Coastguard Worker        if count:
1076*cda5da8dSAndroid Build Coastguard Worker            self.data = self.data[:offset] + self.data[offset+count:]
1077*cda5da8dSAndroid Build Coastguard Worker
1078*cda5da8dSAndroid Build Coastguard Worker    def replaceData(self, offset, count, arg):
1079*cda5da8dSAndroid Build Coastguard Worker        if offset < 0:
1080*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.IndexSizeErr("offset cannot be negative")
1081*cda5da8dSAndroid Build Coastguard Worker        if offset >= len(self.data):
1082*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
1083*cda5da8dSAndroid Build Coastguard Worker        if count < 0:
1084*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.IndexSizeErr("count cannot be negative")
1085*cda5da8dSAndroid Build Coastguard Worker        if count:
1086*cda5da8dSAndroid Build Coastguard Worker            self.data = "%s%s%s" % (
1087*cda5da8dSAndroid Build Coastguard Worker                self.data[:offset], arg, self.data[offset+count:])
1088*cda5da8dSAndroid Build Coastguard Worker
1089*cda5da8dSAndroid Build Coastguard Workerdefproperty(CharacterData, "length", doc="Length of the string data.")
1090*cda5da8dSAndroid Build Coastguard Worker
1091*cda5da8dSAndroid Build Coastguard Worker
1092*cda5da8dSAndroid Build Coastguard Workerclass Text(CharacterData):
1093*cda5da8dSAndroid Build Coastguard Worker    __slots__ = ()
1094*cda5da8dSAndroid Build Coastguard Worker
1095*cda5da8dSAndroid Build Coastguard Worker    nodeType = Node.TEXT_NODE
1096*cda5da8dSAndroid Build Coastguard Worker    nodeName = "#text"
1097*cda5da8dSAndroid Build Coastguard Worker    attributes = None
1098*cda5da8dSAndroid Build Coastguard Worker
1099*cda5da8dSAndroid Build Coastguard Worker    def splitText(self, offset):
1100*cda5da8dSAndroid Build Coastguard Worker        if offset < 0 or offset > len(self.data):
1101*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.IndexSizeErr("illegal offset value")
1102*cda5da8dSAndroid Build Coastguard Worker        newText = self.__class__()
1103*cda5da8dSAndroid Build Coastguard Worker        newText.data = self.data[offset:]
1104*cda5da8dSAndroid Build Coastguard Worker        newText.ownerDocument = self.ownerDocument
1105*cda5da8dSAndroid Build Coastguard Worker        next = self.nextSibling
1106*cda5da8dSAndroid Build Coastguard Worker        if self.parentNode and self in self.parentNode.childNodes:
1107*cda5da8dSAndroid Build Coastguard Worker            if next is None:
1108*cda5da8dSAndroid Build Coastguard Worker                self.parentNode.appendChild(newText)
1109*cda5da8dSAndroid Build Coastguard Worker            else:
1110*cda5da8dSAndroid Build Coastguard Worker                self.parentNode.insertBefore(newText, next)
1111*cda5da8dSAndroid Build Coastguard Worker        self.data = self.data[:offset]
1112*cda5da8dSAndroid Build Coastguard Worker        return newText
1113*cda5da8dSAndroid Build Coastguard Worker
1114*cda5da8dSAndroid Build Coastguard Worker    def writexml(self, writer, indent="", addindent="", newl=""):
1115*cda5da8dSAndroid Build Coastguard Worker        _write_data(writer, "%s%s%s" % (indent, self.data, newl))
1116*cda5da8dSAndroid Build Coastguard Worker
1117*cda5da8dSAndroid Build Coastguard Worker    # DOM Level 3 (WD 9 April 2002)
1118*cda5da8dSAndroid Build Coastguard Worker
1119*cda5da8dSAndroid Build Coastguard Worker    def _get_wholeText(self):
1120*cda5da8dSAndroid Build Coastguard Worker        L = [self.data]
1121*cda5da8dSAndroid Build Coastguard Worker        n = self.previousSibling
1122*cda5da8dSAndroid Build Coastguard Worker        while n is not None:
1123*cda5da8dSAndroid Build Coastguard Worker            if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1124*cda5da8dSAndroid Build Coastguard Worker                L.insert(0, n.data)
1125*cda5da8dSAndroid Build Coastguard Worker                n = n.previousSibling
1126*cda5da8dSAndroid Build Coastguard Worker            else:
1127*cda5da8dSAndroid Build Coastguard Worker                break
1128*cda5da8dSAndroid Build Coastguard Worker        n = self.nextSibling
1129*cda5da8dSAndroid Build Coastguard Worker        while n is not None:
1130*cda5da8dSAndroid Build Coastguard Worker            if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1131*cda5da8dSAndroid Build Coastguard Worker                L.append(n.data)
1132*cda5da8dSAndroid Build Coastguard Worker                n = n.nextSibling
1133*cda5da8dSAndroid Build Coastguard Worker            else:
1134*cda5da8dSAndroid Build Coastguard Worker                break
1135*cda5da8dSAndroid Build Coastguard Worker        return ''.join(L)
1136*cda5da8dSAndroid Build Coastguard Worker
1137*cda5da8dSAndroid Build Coastguard Worker    def replaceWholeText(self, content):
1138*cda5da8dSAndroid Build Coastguard Worker        # XXX This needs to be seriously changed if minidom ever
1139*cda5da8dSAndroid Build Coastguard Worker        # supports EntityReference nodes.
1140*cda5da8dSAndroid Build Coastguard Worker        parent = self.parentNode
1141*cda5da8dSAndroid Build Coastguard Worker        n = self.previousSibling
1142*cda5da8dSAndroid Build Coastguard Worker        while n is not None:
1143*cda5da8dSAndroid Build Coastguard Worker            if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1144*cda5da8dSAndroid Build Coastguard Worker                next = n.previousSibling
1145*cda5da8dSAndroid Build Coastguard Worker                parent.removeChild(n)
1146*cda5da8dSAndroid Build Coastguard Worker                n = next
1147*cda5da8dSAndroid Build Coastguard Worker            else:
1148*cda5da8dSAndroid Build Coastguard Worker                break
1149*cda5da8dSAndroid Build Coastguard Worker        n = self.nextSibling
1150*cda5da8dSAndroid Build Coastguard Worker        if not content:
1151*cda5da8dSAndroid Build Coastguard Worker            parent.removeChild(self)
1152*cda5da8dSAndroid Build Coastguard Worker        while n is not None:
1153*cda5da8dSAndroid Build Coastguard Worker            if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
1154*cda5da8dSAndroid Build Coastguard Worker                next = n.nextSibling
1155*cda5da8dSAndroid Build Coastguard Worker                parent.removeChild(n)
1156*cda5da8dSAndroid Build Coastguard Worker                n = next
1157*cda5da8dSAndroid Build Coastguard Worker            else:
1158*cda5da8dSAndroid Build Coastguard Worker                break
1159*cda5da8dSAndroid Build Coastguard Worker        if content:
1160*cda5da8dSAndroid Build Coastguard Worker            self.data = content
1161*cda5da8dSAndroid Build Coastguard Worker            return self
1162*cda5da8dSAndroid Build Coastguard Worker        else:
1163*cda5da8dSAndroid Build Coastguard Worker            return None
1164*cda5da8dSAndroid Build Coastguard Worker
1165*cda5da8dSAndroid Build Coastguard Worker    def _get_isWhitespaceInElementContent(self):
1166*cda5da8dSAndroid Build Coastguard Worker        if self.data.strip():
1167*cda5da8dSAndroid Build Coastguard Worker            return False
1168*cda5da8dSAndroid Build Coastguard Worker        elem = _get_containing_element(self)
1169*cda5da8dSAndroid Build Coastguard Worker        if elem is None:
1170*cda5da8dSAndroid Build Coastguard Worker            return False
1171*cda5da8dSAndroid Build Coastguard Worker        info = self.ownerDocument._get_elem_info(elem)
1172*cda5da8dSAndroid Build Coastguard Worker        if info is None:
1173*cda5da8dSAndroid Build Coastguard Worker            return False
1174*cda5da8dSAndroid Build Coastguard Worker        else:
1175*cda5da8dSAndroid Build Coastguard Worker            return info.isElementContent()
1176*cda5da8dSAndroid Build Coastguard Worker
1177*cda5da8dSAndroid Build Coastguard Workerdefproperty(Text, "isWhitespaceInElementContent",
1178*cda5da8dSAndroid Build Coastguard Worker            doc="True iff this text node contains only whitespace"
1179*cda5da8dSAndroid Build Coastguard Worker                " and is in element content.")
1180*cda5da8dSAndroid Build Coastguard Workerdefproperty(Text, "wholeText",
1181*cda5da8dSAndroid Build Coastguard Worker            doc="The text of all logically-adjacent text nodes.")
1182*cda5da8dSAndroid Build Coastguard Worker
1183*cda5da8dSAndroid Build Coastguard Worker
1184*cda5da8dSAndroid Build Coastguard Workerdef _get_containing_element(node):
1185*cda5da8dSAndroid Build Coastguard Worker    c = node.parentNode
1186*cda5da8dSAndroid Build Coastguard Worker    while c is not None:
1187*cda5da8dSAndroid Build Coastguard Worker        if c.nodeType == Node.ELEMENT_NODE:
1188*cda5da8dSAndroid Build Coastguard Worker            return c
1189*cda5da8dSAndroid Build Coastguard Worker        c = c.parentNode
1190*cda5da8dSAndroid Build Coastguard Worker    return None
1191*cda5da8dSAndroid Build Coastguard Worker
1192*cda5da8dSAndroid Build Coastguard Workerdef _get_containing_entref(node):
1193*cda5da8dSAndroid Build Coastguard Worker    c = node.parentNode
1194*cda5da8dSAndroid Build Coastguard Worker    while c is not None:
1195*cda5da8dSAndroid Build Coastguard Worker        if c.nodeType == Node.ENTITY_REFERENCE_NODE:
1196*cda5da8dSAndroid Build Coastguard Worker            return c
1197*cda5da8dSAndroid Build Coastguard Worker        c = c.parentNode
1198*cda5da8dSAndroid Build Coastguard Worker    return None
1199*cda5da8dSAndroid Build Coastguard Worker
1200*cda5da8dSAndroid Build Coastguard Worker
1201*cda5da8dSAndroid Build Coastguard Workerclass Comment(CharacterData):
1202*cda5da8dSAndroid Build Coastguard Worker    nodeType = Node.COMMENT_NODE
1203*cda5da8dSAndroid Build Coastguard Worker    nodeName = "#comment"
1204*cda5da8dSAndroid Build Coastguard Worker
1205*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, data):
1206*cda5da8dSAndroid Build Coastguard Worker        CharacterData.__init__(self)
1207*cda5da8dSAndroid Build Coastguard Worker        self._data = data
1208*cda5da8dSAndroid Build Coastguard Worker
1209*cda5da8dSAndroid Build Coastguard Worker    def writexml(self, writer, indent="", addindent="", newl=""):
1210*cda5da8dSAndroid Build Coastguard Worker        if "--" in self.data:
1211*cda5da8dSAndroid Build Coastguard Worker            raise ValueError("'--' is not allowed in a comment node")
1212*cda5da8dSAndroid Build Coastguard Worker        writer.write("%s<!--%s-->%s" % (indent, self.data, newl))
1213*cda5da8dSAndroid Build Coastguard Worker
1214*cda5da8dSAndroid Build Coastguard Worker
1215*cda5da8dSAndroid Build Coastguard Workerclass CDATASection(Text):
1216*cda5da8dSAndroid Build Coastguard Worker    __slots__ = ()
1217*cda5da8dSAndroid Build Coastguard Worker
1218*cda5da8dSAndroid Build Coastguard Worker    nodeType = Node.CDATA_SECTION_NODE
1219*cda5da8dSAndroid Build Coastguard Worker    nodeName = "#cdata-section"
1220*cda5da8dSAndroid Build Coastguard Worker
1221*cda5da8dSAndroid Build Coastguard Worker    def writexml(self, writer, indent="", addindent="", newl=""):
1222*cda5da8dSAndroid Build Coastguard Worker        if self.data.find("]]>") >= 0:
1223*cda5da8dSAndroid Build Coastguard Worker            raise ValueError("']]>' not allowed in a CDATA section")
1224*cda5da8dSAndroid Build Coastguard Worker        writer.write("<![CDATA[%s]]>" % self.data)
1225*cda5da8dSAndroid Build Coastguard Worker
1226*cda5da8dSAndroid Build Coastguard Worker
1227*cda5da8dSAndroid Build Coastguard Workerclass ReadOnlySequentialNamedNodeMap(object):
1228*cda5da8dSAndroid Build Coastguard Worker    __slots__ = '_seq',
1229*cda5da8dSAndroid Build Coastguard Worker
1230*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, seq=()):
1231*cda5da8dSAndroid Build Coastguard Worker        # seq should be a list or tuple
1232*cda5da8dSAndroid Build Coastguard Worker        self._seq = seq
1233*cda5da8dSAndroid Build Coastguard Worker
1234*cda5da8dSAndroid Build Coastguard Worker    def __len__(self):
1235*cda5da8dSAndroid Build Coastguard Worker        return len(self._seq)
1236*cda5da8dSAndroid Build Coastguard Worker
1237*cda5da8dSAndroid Build Coastguard Worker    def _get_length(self):
1238*cda5da8dSAndroid Build Coastguard Worker        return len(self._seq)
1239*cda5da8dSAndroid Build Coastguard Worker
1240*cda5da8dSAndroid Build Coastguard Worker    def getNamedItem(self, name):
1241*cda5da8dSAndroid Build Coastguard Worker        for n in self._seq:
1242*cda5da8dSAndroid Build Coastguard Worker            if n.nodeName == name:
1243*cda5da8dSAndroid Build Coastguard Worker                return n
1244*cda5da8dSAndroid Build Coastguard Worker
1245*cda5da8dSAndroid Build Coastguard Worker    def getNamedItemNS(self, namespaceURI, localName):
1246*cda5da8dSAndroid Build Coastguard Worker        for n in self._seq:
1247*cda5da8dSAndroid Build Coastguard Worker            if n.namespaceURI == namespaceURI and n.localName == localName:
1248*cda5da8dSAndroid Build Coastguard Worker                return n
1249*cda5da8dSAndroid Build Coastguard Worker
1250*cda5da8dSAndroid Build Coastguard Worker    def __getitem__(self, name_or_tuple):
1251*cda5da8dSAndroid Build Coastguard Worker        if isinstance(name_or_tuple, tuple):
1252*cda5da8dSAndroid Build Coastguard Worker            node = self.getNamedItemNS(*name_or_tuple)
1253*cda5da8dSAndroid Build Coastguard Worker        else:
1254*cda5da8dSAndroid Build Coastguard Worker            node = self.getNamedItem(name_or_tuple)
1255*cda5da8dSAndroid Build Coastguard Worker        if node is None:
1256*cda5da8dSAndroid Build Coastguard Worker            raise KeyError(name_or_tuple)
1257*cda5da8dSAndroid Build Coastguard Worker        return node
1258*cda5da8dSAndroid Build Coastguard Worker
1259*cda5da8dSAndroid Build Coastguard Worker    def item(self, index):
1260*cda5da8dSAndroid Build Coastguard Worker        if index < 0:
1261*cda5da8dSAndroid Build Coastguard Worker            return None
1262*cda5da8dSAndroid Build Coastguard Worker        try:
1263*cda5da8dSAndroid Build Coastguard Worker            return self._seq[index]
1264*cda5da8dSAndroid Build Coastguard Worker        except IndexError:
1265*cda5da8dSAndroid Build Coastguard Worker            return None
1266*cda5da8dSAndroid Build Coastguard Worker
1267*cda5da8dSAndroid Build Coastguard Worker    def removeNamedItem(self, name):
1268*cda5da8dSAndroid Build Coastguard Worker        raise xml.dom.NoModificationAllowedErr(
1269*cda5da8dSAndroid Build Coastguard Worker            "NamedNodeMap instance is read-only")
1270*cda5da8dSAndroid Build Coastguard Worker
1271*cda5da8dSAndroid Build Coastguard Worker    def removeNamedItemNS(self, namespaceURI, localName):
1272*cda5da8dSAndroid Build Coastguard Worker        raise xml.dom.NoModificationAllowedErr(
1273*cda5da8dSAndroid Build Coastguard Worker            "NamedNodeMap instance is read-only")
1274*cda5da8dSAndroid Build Coastguard Worker
1275*cda5da8dSAndroid Build Coastguard Worker    def setNamedItem(self, node):
1276*cda5da8dSAndroid Build Coastguard Worker        raise xml.dom.NoModificationAllowedErr(
1277*cda5da8dSAndroid Build Coastguard Worker            "NamedNodeMap instance is read-only")
1278*cda5da8dSAndroid Build Coastguard Worker
1279*cda5da8dSAndroid Build Coastguard Worker    def setNamedItemNS(self, node):
1280*cda5da8dSAndroid Build Coastguard Worker        raise xml.dom.NoModificationAllowedErr(
1281*cda5da8dSAndroid Build Coastguard Worker            "NamedNodeMap instance is read-only")
1282*cda5da8dSAndroid Build Coastguard Worker
1283*cda5da8dSAndroid Build Coastguard Worker    def __getstate__(self):
1284*cda5da8dSAndroid Build Coastguard Worker        return [self._seq]
1285*cda5da8dSAndroid Build Coastguard Worker
1286*cda5da8dSAndroid Build Coastguard Worker    def __setstate__(self, state):
1287*cda5da8dSAndroid Build Coastguard Worker        self._seq = state[0]
1288*cda5da8dSAndroid Build Coastguard Worker
1289*cda5da8dSAndroid Build Coastguard Workerdefproperty(ReadOnlySequentialNamedNodeMap, "length",
1290*cda5da8dSAndroid Build Coastguard Worker            doc="Number of entries in the NamedNodeMap.")
1291*cda5da8dSAndroid Build Coastguard Worker
1292*cda5da8dSAndroid Build Coastguard Worker
1293*cda5da8dSAndroid Build Coastguard Workerclass Identified:
1294*cda5da8dSAndroid Build Coastguard Worker    """Mix-in class that supports the publicId and systemId attributes."""
1295*cda5da8dSAndroid Build Coastguard Worker
1296*cda5da8dSAndroid Build Coastguard Worker    __slots__ = 'publicId', 'systemId'
1297*cda5da8dSAndroid Build Coastguard Worker
1298*cda5da8dSAndroid Build Coastguard Worker    def _identified_mixin_init(self, publicId, systemId):
1299*cda5da8dSAndroid Build Coastguard Worker        self.publicId = publicId
1300*cda5da8dSAndroid Build Coastguard Worker        self.systemId = systemId
1301*cda5da8dSAndroid Build Coastguard Worker
1302*cda5da8dSAndroid Build Coastguard Worker    def _get_publicId(self):
1303*cda5da8dSAndroid Build Coastguard Worker        return self.publicId
1304*cda5da8dSAndroid Build Coastguard Worker
1305*cda5da8dSAndroid Build Coastguard Worker    def _get_systemId(self):
1306*cda5da8dSAndroid Build Coastguard Worker        return self.systemId
1307*cda5da8dSAndroid Build Coastguard Worker
1308*cda5da8dSAndroid Build Coastguard Workerclass DocumentType(Identified, Childless, Node):
1309*cda5da8dSAndroid Build Coastguard Worker    nodeType = Node.DOCUMENT_TYPE_NODE
1310*cda5da8dSAndroid Build Coastguard Worker    nodeValue = None
1311*cda5da8dSAndroid Build Coastguard Worker    name = None
1312*cda5da8dSAndroid Build Coastguard Worker    publicId = None
1313*cda5da8dSAndroid Build Coastguard Worker    systemId = None
1314*cda5da8dSAndroid Build Coastguard Worker    internalSubset = None
1315*cda5da8dSAndroid Build Coastguard Worker
1316*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, qualifiedName):
1317*cda5da8dSAndroid Build Coastguard Worker        self.entities = ReadOnlySequentialNamedNodeMap()
1318*cda5da8dSAndroid Build Coastguard Worker        self.notations = ReadOnlySequentialNamedNodeMap()
1319*cda5da8dSAndroid Build Coastguard Worker        if qualifiedName:
1320*cda5da8dSAndroid Build Coastguard Worker            prefix, localname = _nssplit(qualifiedName)
1321*cda5da8dSAndroid Build Coastguard Worker            self.name = localname
1322*cda5da8dSAndroid Build Coastguard Worker        self.nodeName = self.name
1323*cda5da8dSAndroid Build Coastguard Worker
1324*cda5da8dSAndroid Build Coastguard Worker    def _get_internalSubset(self):
1325*cda5da8dSAndroid Build Coastguard Worker        return self.internalSubset
1326*cda5da8dSAndroid Build Coastguard Worker
1327*cda5da8dSAndroid Build Coastguard Worker    def cloneNode(self, deep):
1328*cda5da8dSAndroid Build Coastguard Worker        if self.ownerDocument is None:
1329*cda5da8dSAndroid Build Coastguard Worker            # it's ok
1330*cda5da8dSAndroid Build Coastguard Worker            clone = DocumentType(None)
1331*cda5da8dSAndroid Build Coastguard Worker            clone.name = self.name
1332*cda5da8dSAndroid Build Coastguard Worker            clone.nodeName = self.name
1333*cda5da8dSAndroid Build Coastguard Worker            operation = xml.dom.UserDataHandler.NODE_CLONED
1334*cda5da8dSAndroid Build Coastguard Worker            if deep:
1335*cda5da8dSAndroid Build Coastguard Worker                clone.entities._seq = []
1336*cda5da8dSAndroid Build Coastguard Worker                clone.notations._seq = []
1337*cda5da8dSAndroid Build Coastguard Worker                for n in self.notations._seq:
1338*cda5da8dSAndroid Build Coastguard Worker                    notation = Notation(n.nodeName, n.publicId, n.systemId)
1339*cda5da8dSAndroid Build Coastguard Worker                    clone.notations._seq.append(notation)
1340*cda5da8dSAndroid Build Coastguard Worker                    n._call_user_data_handler(operation, n, notation)
1341*cda5da8dSAndroid Build Coastguard Worker                for e in self.entities._seq:
1342*cda5da8dSAndroid Build Coastguard Worker                    entity = Entity(e.nodeName, e.publicId, e.systemId,
1343*cda5da8dSAndroid Build Coastguard Worker                                    e.notationName)
1344*cda5da8dSAndroid Build Coastguard Worker                    entity.actualEncoding = e.actualEncoding
1345*cda5da8dSAndroid Build Coastguard Worker                    entity.encoding = e.encoding
1346*cda5da8dSAndroid Build Coastguard Worker                    entity.version = e.version
1347*cda5da8dSAndroid Build Coastguard Worker                    clone.entities._seq.append(entity)
1348*cda5da8dSAndroid Build Coastguard Worker                    e._call_user_data_handler(operation, e, entity)
1349*cda5da8dSAndroid Build Coastguard Worker            self._call_user_data_handler(operation, self, clone)
1350*cda5da8dSAndroid Build Coastguard Worker            return clone
1351*cda5da8dSAndroid Build Coastguard Worker        else:
1352*cda5da8dSAndroid Build Coastguard Worker            return None
1353*cda5da8dSAndroid Build Coastguard Worker
1354*cda5da8dSAndroid Build Coastguard Worker    def writexml(self, writer, indent="", addindent="", newl=""):
1355*cda5da8dSAndroid Build Coastguard Worker        writer.write("<!DOCTYPE ")
1356*cda5da8dSAndroid Build Coastguard Worker        writer.write(self.name)
1357*cda5da8dSAndroid Build Coastguard Worker        if self.publicId:
1358*cda5da8dSAndroid Build Coastguard Worker            writer.write("%s  PUBLIC '%s'%s  '%s'"
1359*cda5da8dSAndroid Build Coastguard Worker                         % (newl, self.publicId, newl, self.systemId))
1360*cda5da8dSAndroid Build Coastguard Worker        elif self.systemId:
1361*cda5da8dSAndroid Build Coastguard Worker            writer.write("%s  SYSTEM '%s'" % (newl, self.systemId))
1362*cda5da8dSAndroid Build Coastguard Worker        if self.internalSubset is not None:
1363*cda5da8dSAndroid Build Coastguard Worker            writer.write(" [")
1364*cda5da8dSAndroid Build Coastguard Worker            writer.write(self.internalSubset)
1365*cda5da8dSAndroid Build Coastguard Worker            writer.write("]")
1366*cda5da8dSAndroid Build Coastguard Worker        writer.write(">"+newl)
1367*cda5da8dSAndroid Build Coastguard Worker
1368*cda5da8dSAndroid Build Coastguard Workerclass Entity(Identified, Node):
1369*cda5da8dSAndroid Build Coastguard Worker    attributes = None
1370*cda5da8dSAndroid Build Coastguard Worker    nodeType = Node.ENTITY_NODE
1371*cda5da8dSAndroid Build Coastguard Worker    nodeValue = None
1372*cda5da8dSAndroid Build Coastguard Worker
1373*cda5da8dSAndroid Build Coastguard Worker    actualEncoding = None
1374*cda5da8dSAndroid Build Coastguard Worker    encoding = None
1375*cda5da8dSAndroid Build Coastguard Worker    version = None
1376*cda5da8dSAndroid Build Coastguard Worker
1377*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, name, publicId, systemId, notation):
1378*cda5da8dSAndroid Build Coastguard Worker        self.nodeName = name
1379*cda5da8dSAndroid Build Coastguard Worker        self.notationName = notation
1380*cda5da8dSAndroid Build Coastguard Worker        self.childNodes = NodeList()
1381*cda5da8dSAndroid Build Coastguard Worker        self._identified_mixin_init(publicId, systemId)
1382*cda5da8dSAndroid Build Coastguard Worker
1383*cda5da8dSAndroid Build Coastguard Worker    def _get_actualEncoding(self):
1384*cda5da8dSAndroid Build Coastguard Worker        return self.actualEncoding
1385*cda5da8dSAndroid Build Coastguard Worker
1386*cda5da8dSAndroid Build Coastguard Worker    def _get_encoding(self):
1387*cda5da8dSAndroid Build Coastguard Worker        return self.encoding
1388*cda5da8dSAndroid Build Coastguard Worker
1389*cda5da8dSAndroid Build Coastguard Worker    def _get_version(self):
1390*cda5da8dSAndroid Build Coastguard Worker        return self.version
1391*cda5da8dSAndroid Build Coastguard Worker
1392*cda5da8dSAndroid Build Coastguard Worker    def appendChild(self, newChild):
1393*cda5da8dSAndroid Build Coastguard Worker        raise xml.dom.HierarchyRequestErr(
1394*cda5da8dSAndroid Build Coastguard Worker            "cannot append children to an entity node")
1395*cda5da8dSAndroid Build Coastguard Worker
1396*cda5da8dSAndroid Build Coastguard Worker    def insertBefore(self, newChild, refChild):
1397*cda5da8dSAndroid Build Coastguard Worker        raise xml.dom.HierarchyRequestErr(
1398*cda5da8dSAndroid Build Coastguard Worker            "cannot insert children below an entity node")
1399*cda5da8dSAndroid Build Coastguard Worker
1400*cda5da8dSAndroid Build Coastguard Worker    def removeChild(self, oldChild):
1401*cda5da8dSAndroid Build Coastguard Worker        raise xml.dom.HierarchyRequestErr(
1402*cda5da8dSAndroid Build Coastguard Worker            "cannot remove children from an entity node")
1403*cda5da8dSAndroid Build Coastguard Worker
1404*cda5da8dSAndroid Build Coastguard Worker    def replaceChild(self, newChild, oldChild):
1405*cda5da8dSAndroid Build Coastguard Worker        raise xml.dom.HierarchyRequestErr(
1406*cda5da8dSAndroid Build Coastguard Worker            "cannot replace children of an entity node")
1407*cda5da8dSAndroid Build Coastguard Worker
1408*cda5da8dSAndroid Build Coastguard Workerclass Notation(Identified, Childless, Node):
1409*cda5da8dSAndroid Build Coastguard Worker    nodeType = Node.NOTATION_NODE
1410*cda5da8dSAndroid Build Coastguard Worker    nodeValue = None
1411*cda5da8dSAndroid Build Coastguard Worker
1412*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, name, publicId, systemId):
1413*cda5da8dSAndroid Build Coastguard Worker        self.nodeName = name
1414*cda5da8dSAndroid Build Coastguard Worker        self._identified_mixin_init(publicId, systemId)
1415*cda5da8dSAndroid Build Coastguard Worker
1416*cda5da8dSAndroid Build Coastguard Worker
1417*cda5da8dSAndroid Build Coastguard Workerclass DOMImplementation(DOMImplementationLS):
1418*cda5da8dSAndroid Build Coastguard Worker    _features = [("core", "1.0"),
1419*cda5da8dSAndroid Build Coastguard Worker                 ("core", "2.0"),
1420*cda5da8dSAndroid Build Coastguard Worker                 ("core", None),
1421*cda5da8dSAndroid Build Coastguard Worker                 ("xml", "1.0"),
1422*cda5da8dSAndroid Build Coastguard Worker                 ("xml", "2.0"),
1423*cda5da8dSAndroid Build Coastguard Worker                 ("xml", None),
1424*cda5da8dSAndroid Build Coastguard Worker                 ("ls-load", "3.0"),
1425*cda5da8dSAndroid Build Coastguard Worker                 ("ls-load", None),
1426*cda5da8dSAndroid Build Coastguard Worker                 ]
1427*cda5da8dSAndroid Build Coastguard Worker
1428*cda5da8dSAndroid Build Coastguard Worker    def hasFeature(self, feature, version):
1429*cda5da8dSAndroid Build Coastguard Worker        if version == "":
1430*cda5da8dSAndroid Build Coastguard Worker            version = None
1431*cda5da8dSAndroid Build Coastguard Worker        return (feature.lower(), version) in self._features
1432*cda5da8dSAndroid Build Coastguard Worker
1433*cda5da8dSAndroid Build Coastguard Worker    def createDocument(self, namespaceURI, qualifiedName, doctype):
1434*cda5da8dSAndroid Build Coastguard Worker        if doctype and doctype.parentNode is not None:
1435*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.WrongDocumentErr(
1436*cda5da8dSAndroid Build Coastguard Worker                "doctype object owned by another DOM tree")
1437*cda5da8dSAndroid Build Coastguard Worker        doc = self._create_document()
1438*cda5da8dSAndroid Build Coastguard Worker
1439*cda5da8dSAndroid Build Coastguard Worker        add_root_element = not (namespaceURI is None
1440*cda5da8dSAndroid Build Coastguard Worker                                and qualifiedName is None
1441*cda5da8dSAndroid Build Coastguard Worker                                and doctype is None)
1442*cda5da8dSAndroid Build Coastguard Worker
1443*cda5da8dSAndroid Build Coastguard Worker        if not qualifiedName and add_root_element:
1444*cda5da8dSAndroid Build Coastguard Worker            # The spec is unclear what to raise here; SyntaxErr
1445*cda5da8dSAndroid Build Coastguard Worker            # would be the other obvious candidate. Since Xerces raises
1446*cda5da8dSAndroid Build Coastguard Worker            # InvalidCharacterErr, and since SyntaxErr is not listed
1447*cda5da8dSAndroid Build Coastguard Worker            # for createDocument, that seems to be the better choice.
1448*cda5da8dSAndroid Build Coastguard Worker            # XXX: need to check for illegal characters here and in
1449*cda5da8dSAndroid Build Coastguard Worker            # createElement.
1450*cda5da8dSAndroid Build Coastguard Worker
1451*cda5da8dSAndroid Build Coastguard Worker            # DOM Level III clears this up when talking about the return value
1452*cda5da8dSAndroid Build Coastguard Worker            # of this function.  If namespaceURI, qName and DocType are
1453*cda5da8dSAndroid Build Coastguard Worker            # Null the document is returned without a document element
1454*cda5da8dSAndroid Build Coastguard Worker            # Otherwise if doctype or namespaceURI are not None
1455*cda5da8dSAndroid Build Coastguard Worker            # Then we go back to the above problem
1456*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.InvalidCharacterErr("Element with no name")
1457*cda5da8dSAndroid Build Coastguard Worker
1458*cda5da8dSAndroid Build Coastguard Worker        if add_root_element:
1459*cda5da8dSAndroid Build Coastguard Worker            prefix, localname = _nssplit(qualifiedName)
1460*cda5da8dSAndroid Build Coastguard Worker            if prefix == "xml" \
1461*cda5da8dSAndroid Build Coastguard Worker               and namespaceURI != "http://www.w3.org/XML/1998/namespace":
1462*cda5da8dSAndroid Build Coastguard Worker                raise xml.dom.NamespaceErr("illegal use of 'xml' prefix")
1463*cda5da8dSAndroid Build Coastguard Worker            if prefix and not namespaceURI:
1464*cda5da8dSAndroid Build Coastguard Worker                raise xml.dom.NamespaceErr(
1465*cda5da8dSAndroid Build Coastguard Worker                    "illegal use of prefix without namespaces")
1466*cda5da8dSAndroid Build Coastguard Worker            element = doc.createElementNS(namespaceURI, qualifiedName)
1467*cda5da8dSAndroid Build Coastguard Worker            if doctype:
1468*cda5da8dSAndroid Build Coastguard Worker                doc.appendChild(doctype)
1469*cda5da8dSAndroid Build Coastguard Worker            doc.appendChild(element)
1470*cda5da8dSAndroid Build Coastguard Worker
1471*cda5da8dSAndroid Build Coastguard Worker        if doctype:
1472*cda5da8dSAndroid Build Coastguard Worker            doctype.parentNode = doctype.ownerDocument = doc
1473*cda5da8dSAndroid Build Coastguard Worker
1474*cda5da8dSAndroid Build Coastguard Worker        doc.doctype = doctype
1475*cda5da8dSAndroid Build Coastguard Worker        doc.implementation = self
1476*cda5da8dSAndroid Build Coastguard Worker        return doc
1477*cda5da8dSAndroid Build Coastguard Worker
1478*cda5da8dSAndroid Build Coastguard Worker    def createDocumentType(self, qualifiedName, publicId, systemId):
1479*cda5da8dSAndroid Build Coastguard Worker        doctype = DocumentType(qualifiedName)
1480*cda5da8dSAndroid Build Coastguard Worker        doctype.publicId = publicId
1481*cda5da8dSAndroid Build Coastguard Worker        doctype.systemId = systemId
1482*cda5da8dSAndroid Build Coastguard Worker        return doctype
1483*cda5da8dSAndroid Build Coastguard Worker
1484*cda5da8dSAndroid Build Coastguard Worker    # DOM Level 3 (WD 9 April 2002)
1485*cda5da8dSAndroid Build Coastguard Worker
1486*cda5da8dSAndroid Build Coastguard Worker    def getInterface(self, feature):
1487*cda5da8dSAndroid Build Coastguard Worker        if self.hasFeature(feature, None):
1488*cda5da8dSAndroid Build Coastguard Worker            return self
1489*cda5da8dSAndroid Build Coastguard Worker        else:
1490*cda5da8dSAndroid Build Coastguard Worker            return None
1491*cda5da8dSAndroid Build Coastguard Worker
1492*cda5da8dSAndroid Build Coastguard Worker    # internal
1493*cda5da8dSAndroid Build Coastguard Worker    def _create_document(self):
1494*cda5da8dSAndroid Build Coastguard Worker        return Document()
1495*cda5da8dSAndroid Build Coastguard Worker
1496*cda5da8dSAndroid Build Coastguard Workerclass ElementInfo(object):
1497*cda5da8dSAndroid Build Coastguard Worker    """Object that represents content-model information for an element.
1498*cda5da8dSAndroid Build Coastguard Worker
1499*cda5da8dSAndroid Build Coastguard Worker    This implementation is not expected to be used in practice; DOM
1500*cda5da8dSAndroid Build Coastguard Worker    builders should provide implementations which do the right thing
1501*cda5da8dSAndroid Build Coastguard Worker    using information available to it.
1502*cda5da8dSAndroid Build Coastguard Worker
1503*cda5da8dSAndroid Build Coastguard Worker    """
1504*cda5da8dSAndroid Build Coastguard Worker
1505*cda5da8dSAndroid Build Coastguard Worker    __slots__ = 'tagName',
1506*cda5da8dSAndroid Build Coastguard Worker
1507*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, name):
1508*cda5da8dSAndroid Build Coastguard Worker        self.tagName = name
1509*cda5da8dSAndroid Build Coastguard Worker
1510*cda5da8dSAndroid Build Coastguard Worker    def getAttributeType(self, aname):
1511*cda5da8dSAndroid Build Coastguard Worker        return _no_type
1512*cda5da8dSAndroid Build Coastguard Worker
1513*cda5da8dSAndroid Build Coastguard Worker    def getAttributeTypeNS(self, namespaceURI, localName):
1514*cda5da8dSAndroid Build Coastguard Worker        return _no_type
1515*cda5da8dSAndroid Build Coastguard Worker
1516*cda5da8dSAndroid Build Coastguard Worker    def isElementContent(self):
1517*cda5da8dSAndroid Build Coastguard Worker        return False
1518*cda5da8dSAndroid Build Coastguard Worker
1519*cda5da8dSAndroid Build Coastguard Worker    def isEmpty(self):
1520*cda5da8dSAndroid Build Coastguard Worker        """Returns true iff this element is declared to have an EMPTY
1521*cda5da8dSAndroid Build Coastguard Worker        content model."""
1522*cda5da8dSAndroid Build Coastguard Worker        return False
1523*cda5da8dSAndroid Build Coastguard Worker
1524*cda5da8dSAndroid Build Coastguard Worker    def isId(self, aname):
1525*cda5da8dSAndroid Build Coastguard Worker        """Returns true iff the named attribute is a DTD-style ID."""
1526*cda5da8dSAndroid Build Coastguard Worker        return False
1527*cda5da8dSAndroid Build Coastguard Worker
1528*cda5da8dSAndroid Build Coastguard Worker    def isIdNS(self, namespaceURI, localName):
1529*cda5da8dSAndroid Build Coastguard Worker        """Returns true iff the identified attribute is a DTD-style ID."""
1530*cda5da8dSAndroid Build Coastguard Worker        return False
1531*cda5da8dSAndroid Build Coastguard Worker
1532*cda5da8dSAndroid Build Coastguard Worker    def __getstate__(self):
1533*cda5da8dSAndroid Build Coastguard Worker        return self.tagName
1534*cda5da8dSAndroid Build Coastguard Worker
1535*cda5da8dSAndroid Build Coastguard Worker    def __setstate__(self, state):
1536*cda5da8dSAndroid Build Coastguard Worker        self.tagName = state
1537*cda5da8dSAndroid Build Coastguard Worker
1538*cda5da8dSAndroid Build Coastguard Workerdef _clear_id_cache(node):
1539*cda5da8dSAndroid Build Coastguard Worker    if node.nodeType == Node.DOCUMENT_NODE:
1540*cda5da8dSAndroid Build Coastguard Worker        node._id_cache.clear()
1541*cda5da8dSAndroid Build Coastguard Worker        node._id_search_stack = None
1542*cda5da8dSAndroid Build Coastguard Worker    elif _in_document(node):
1543*cda5da8dSAndroid Build Coastguard Worker        node.ownerDocument._id_cache.clear()
1544*cda5da8dSAndroid Build Coastguard Worker        node.ownerDocument._id_search_stack= None
1545*cda5da8dSAndroid Build Coastguard Worker
1546*cda5da8dSAndroid Build Coastguard Workerclass Document(Node, DocumentLS):
1547*cda5da8dSAndroid Build Coastguard Worker    __slots__ = ('_elem_info', 'doctype',
1548*cda5da8dSAndroid Build Coastguard Worker                 '_id_search_stack', 'childNodes', '_id_cache')
1549*cda5da8dSAndroid Build Coastguard Worker    _child_node_types = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE,
1550*cda5da8dSAndroid Build Coastguard Worker                         Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE)
1551*cda5da8dSAndroid Build Coastguard Worker
1552*cda5da8dSAndroid Build Coastguard Worker    implementation = DOMImplementation()
1553*cda5da8dSAndroid Build Coastguard Worker    nodeType = Node.DOCUMENT_NODE
1554*cda5da8dSAndroid Build Coastguard Worker    nodeName = "#document"
1555*cda5da8dSAndroid Build Coastguard Worker    nodeValue = None
1556*cda5da8dSAndroid Build Coastguard Worker    attributes = None
1557*cda5da8dSAndroid Build Coastguard Worker    parentNode = None
1558*cda5da8dSAndroid Build Coastguard Worker    previousSibling = nextSibling = None
1559*cda5da8dSAndroid Build Coastguard Worker
1560*cda5da8dSAndroid Build Coastguard Worker
1561*cda5da8dSAndroid Build Coastguard Worker    # Document attributes from Level 3 (WD 9 April 2002)
1562*cda5da8dSAndroid Build Coastguard Worker
1563*cda5da8dSAndroid Build Coastguard Worker    actualEncoding = None
1564*cda5da8dSAndroid Build Coastguard Worker    encoding = None
1565*cda5da8dSAndroid Build Coastguard Worker    standalone = None
1566*cda5da8dSAndroid Build Coastguard Worker    version = None
1567*cda5da8dSAndroid Build Coastguard Worker    strictErrorChecking = False
1568*cda5da8dSAndroid Build Coastguard Worker    errorHandler = None
1569*cda5da8dSAndroid Build Coastguard Worker    documentURI = None
1570*cda5da8dSAndroid Build Coastguard Worker
1571*cda5da8dSAndroid Build Coastguard Worker    _magic_id_count = 0
1572*cda5da8dSAndroid Build Coastguard Worker
1573*cda5da8dSAndroid Build Coastguard Worker    def __init__(self):
1574*cda5da8dSAndroid Build Coastguard Worker        self.doctype = None
1575*cda5da8dSAndroid Build Coastguard Worker        self.childNodes = NodeList()
1576*cda5da8dSAndroid Build Coastguard Worker        # mapping of (namespaceURI, localName) -> ElementInfo
1577*cda5da8dSAndroid Build Coastguard Worker        #        and tagName -> ElementInfo
1578*cda5da8dSAndroid Build Coastguard Worker        self._elem_info = {}
1579*cda5da8dSAndroid Build Coastguard Worker        self._id_cache = {}
1580*cda5da8dSAndroid Build Coastguard Worker        self._id_search_stack = None
1581*cda5da8dSAndroid Build Coastguard Worker
1582*cda5da8dSAndroid Build Coastguard Worker    def _get_elem_info(self, element):
1583*cda5da8dSAndroid Build Coastguard Worker        if element.namespaceURI:
1584*cda5da8dSAndroid Build Coastguard Worker            key = element.namespaceURI, element.localName
1585*cda5da8dSAndroid Build Coastguard Worker        else:
1586*cda5da8dSAndroid Build Coastguard Worker            key = element.tagName
1587*cda5da8dSAndroid Build Coastguard Worker        return self._elem_info.get(key)
1588*cda5da8dSAndroid Build Coastguard Worker
1589*cda5da8dSAndroid Build Coastguard Worker    def _get_actualEncoding(self):
1590*cda5da8dSAndroid Build Coastguard Worker        return self.actualEncoding
1591*cda5da8dSAndroid Build Coastguard Worker
1592*cda5da8dSAndroid Build Coastguard Worker    def _get_doctype(self):
1593*cda5da8dSAndroid Build Coastguard Worker        return self.doctype
1594*cda5da8dSAndroid Build Coastguard Worker
1595*cda5da8dSAndroid Build Coastguard Worker    def _get_documentURI(self):
1596*cda5da8dSAndroid Build Coastguard Worker        return self.documentURI
1597*cda5da8dSAndroid Build Coastguard Worker
1598*cda5da8dSAndroid Build Coastguard Worker    def _get_encoding(self):
1599*cda5da8dSAndroid Build Coastguard Worker        return self.encoding
1600*cda5da8dSAndroid Build Coastguard Worker
1601*cda5da8dSAndroid Build Coastguard Worker    def _get_errorHandler(self):
1602*cda5da8dSAndroid Build Coastguard Worker        return self.errorHandler
1603*cda5da8dSAndroid Build Coastguard Worker
1604*cda5da8dSAndroid Build Coastguard Worker    def _get_standalone(self):
1605*cda5da8dSAndroid Build Coastguard Worker        return self.standalone
1606*cda5da8dSAndroid Build Coastguard Worker
1607*cda5da8dSAndroid Build Coastguard Worker    def _get_strictErrorChecking(self):
1608*cda5da8dSAndroid Build Coastguard Worker        return self.strictErrorChecking
1609*cda5da8dSAndroid Build Coastguard Worker
1610*cda5da8dSAndroid Build Coastguard Worker    def _get_version(self):
1611*cda5da8dSAndroid Build Coastguard Worker        return self.version
1612*cda5da8dSAndroid Build Coastguard Worker
1613*cda5da8dSAndroid Build Coastguard Worker    def appendChild(self, node):
1614*cda5da8dSAndroid Build Coastguard Worker        if node.nodeType not in self._child_node_types:
1615*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.HierarchyRequestErr(
1616*cda5da8dSAndroid Build Coastguard Worker                "%s cannot be child of %s" % (repr(node), repr(self)))
1617*cda5da8dSAndroid Build Coastguard Worker        if node.parentNode is not None:
1618*cda5da8dSAndroid Build Coastguard Worker            # This needs to be done before the next test since this
1619*cda5da8dSAndroid Build Coastguard Worker            # may *be* the document element, in which case it should
1620*cda5da8dSAndroid Build Coastguard Worker            # end up re-ordered to the end.
1621*cda5da8dSAndroid Build Coastguard Worker            node.parentNode.removeChild(node)
1622*cda5da8dSAndroid Build Coastguard Worker
1623*cda5da8dSAndroid Build Coastguard Worker        if node.nodeType == Node.ELEMENT_NODE \
1624*cda5da8dSAndroid Build Coastguard Worker           and self._get_documentElement():
1625*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.HierarchyRequestErr(
1626*cda5da8dSAndroid Build Coastguard Worker                "two document elements disallowed")
1627*cda5da8dSAndroid Build Coastguard Worker        return Node.appendChild(self, node)
1628*cda5da8dSAndroid Build Coastguard Worker
1629*cda5da8dSAndroid Build Coastguard Worker    def removeChild(self, oldChild):
1630*cda5da8dSAndroid Build Coastguard Worker        try:
1631*cda5da8dSAndroid Build Coastguard Worker            self.childNodes.remove(oldChild)
1632*cda5da8dSAndroid Build Coastguard Worker        except ValueError:
1633*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.NotFoundErr()
1634*cda5da8dSAndroid Build Coastguard Worker        oldChild.nextSibling = oldChild.previousSibling = None
1635*cda5da8dSAndroid Build Coastguard Worker        oldChild.parentNode = None
1636*cda5da8dSAndroid Build Coastguard Worker        if self.documentElement is oldChild:
1637*cda5da8dSAndroid Build Coastguard Worker            self.documentElement = None
1638*cda5da8dSAndroid Build Coastguard Worker
1639*cda5da8dSAndroid Build Coastguard Worker        return oldChild
1640*cda5da8dSAndroid Build Coastguard Worker
1641*cda5da8dSAndroid Build Coastguard Worker    def _get_documentElement(self):
1642*cda5da8dSAndroid Build Coastguard Worker        for node in self.childNodes:
1643*cda5da8dSAndroid Build Coastguard Worker            if node.nodeType == Node.ELEMENT_NODE:
1644*cda5da8dSAndroid Build Coastguard Worker                return node
1645*cda5da8dSAndroid Build Coastguard Worker
1646*cda5da8dSAndroid Build Coastguard Worker    def unlink(self):
1647*cda5da8dSAndroid Build Coastguard Worker        if self.doctype is not None:
1648*cda5da8dSAndroid Build Coastguard Worker            self.doctype.unlink()
1649*cda5da8dSAndroid Build Coastguard Worker            self.doctype = None
1650*cda5da8dSAndroid Build Coastguard Worker        Node.unlink(self)
1651*cda5da8dSAndroid Build Coastguard Worker
1652*cda5da8dSAndroid Build Coastguard Worker    def cloneNode(self, deep):
1653*cda5da8dSAndroid Build Coastguard Worker        if not deep:
1654*cda5da8dSAndroid Build Coastguard Worker            return None
1655*cda5da8dSAndroid Build Coastguard Worker        clone = self.implementation.createDocument(None, None, None)
1656*cda5da8dSAndroid Build Coastguard Worker        clone.encoding = self.encoding
1657*cda5da8dSAndroid Build Coastguard Worker        clone.standalone = self.standalone
1658*cda5da8dSAndroid Build Coastguard Worker        clone.version = self.version
1659*cda5da8dSAndroid Build Coastguard Worker        for n in self.childNodes:
1660*cda5da8dSAndroid Build Coastguard Worker            childclone = _clone_node(n, deep, clone)
1661*cda5da8dSAndroid Build Coastguard Worker            assert childclone.ownerDocument.isSameNode(clone)
1662*cda5da8dSAndroid Build Coastguard Worker            clone.childNodes.append(childclone)
1663*cda5da8dSAndroid Build Coastguard Worker            if childclone.nodeType == Node.DOCUMENT_NODE:
1664*cda5da8dSAndroid Build Coastguard Worker                assert clone.documentElement is None
1665*cda5da8dSAndroid Build Coastguard Worker            elif childclone.nodeType == Node.DOCUMENT_TYPE_NODE:
1666*cda5da8dSAndroid Build Coastguard Worker                assert clone.doctype is None
1667*cda5da8dSAndroid Build Coastguard Worker                clone.doctype = childclone
1668*cda5da8dSAndroid Build Coastguard Worker            childclone.parentNode = clone
1669*cda5da8dSAndroid Build Coastguard Worker        self._call_user_data_handler(xml.dom.UserDataHandler.NODE_CLONED,
1670*cda5da8dSAndroid Build Coastguard Worker                                     self, clone)
1671*cda5da8dSAndroid Build Coastguard Worker        return clone
1672*cda5da8dSAndroid Build Coastguard Worker
1673*cda5da8dSAndroid Build Coastguard Worker    def createDocumentFragment(self):
1674*cda5da8dSAndroid Build Coastguard Worker        d = DocumentFragment()
1675*cda5da8dSAndroid Build Coastguard Worker        d.ownerDocument = self
1676*cda5da8dSAndroid Build Coastguard Worker        return d
1677*cda5da8dSAndroid Build Coastguard Worker
1678*cda5da8dSAndroid Build Coastguard Worker    def createElement(self, tagName):
1679*cda5da8dSAndroid Build Coastguard Worker        e = Element(tagName)
1680*cda5da8dSAndroid Build Coastguard Worker        e.ownerDocument = self
1681*cda5da8dSAndroid Build Coastguard Worker        return e
1682*cda5da8dSAndroid Build Coastguard Worker
1683*cda5da8dSAndroid Build Coastguard Worker    def createTextNode(self, data):
1684*cda5da8dSAndroid Build Coastguard Worker        if not isinstance(data, str):
1685*cda5da8dSAndroid Build Coastguard Worker            raise TypeError("node contents must be a string")
1686*cda5da8dSAndroid Build Coastguard Worker        t = Text()
1687*cda5da8dSAndroid Build Coastguard Worker        t.data = data
1688*cda5da8dSAndroid Build Coastguard Worker        t.ownerDocument = self
1689*cda5da8dSAndroid Build Coastguard Worker        return t
1690*cda5da8dSAndroid Build Coastguard Worker
1691*cda5da8dSAndroid Build Coastguard Worker    def createCDATASection(self, data):
1692*cda5da8dSAndroid Build Coastguard Worker        if not isinstance(data, str):
1693*cda5da8dSAndroid Build Coastguard Worker            raise TypeError("node contents must be a string")
1694*cda5da8dSAndroid Build Coastguard Worker        c = CDATASection()
1695*cda5da8dSAndroid Build Coastguard Worker        c.data = data
1696*cda5da8dSAndroid Build Coastguard Worker        c.ownerDocument = self
1697*cda5da8dSAndroid Build Coastguard Worker        return c
1698*cda5da8dSAndroid Build Coastguard Worker
1699*cda5da8dSAndroid Build Coastguard Worker    def createComment(self, data):
1700*cda5da8dSAndroid Build Coastguard Worker        c = Comment(data)
1701*cda5da8dSAndroid Build Coastguard Worker        c.ownerDocument = self
1702*cda5da8dSAndroid Build Coastguard Worker        return c
1703*cda5da8dSAndroid Build Coastguard Worker
1704*cda5da8dSAndroid Build Coastguard Worker    def createProcessingInstruction(self, target, data):
1705*cda5da8dSAndroid Build Coastguard Worker        p = ProcessingInstruction(target, data)
1706*cda5da8dSAndroid Build Coastguard Worker        p.ownerDocument = self
1707*cda5da8dSAndroid Build Coastguard Worker        return p
1708*cda5da8dSAndroid Build Coastguard Worker
1709*cda5da8dSAndroid Build Coastguard Worker    def createAttribute(self, qName):
1710*cda5da8dSAndroid Build Coastguard Worker        a = Attr(qName)
1711*cda5da8dSAndroid Build Coastguard Worker        a.ownerDocument = self
1712*cda5da8dSAndroid Build Coastguard Worker        a.value = ""
1713*cda5da8dSAndroid Build Coastguard Worker        return a
1714*cda5da8dSAndroid Build Coastguard Worker
1715*cda5da8dSAndroid Build Coastguard Worker    def createElementNS(self, namespaceURI, qualifiedName):
1716*cda5da8dSAndroid Build Coastguard Worker        prefix, localName = _nssplit(qualifiedName)
1717*cda5da8dSAndroid Build Coastguard Worker        e = Element(qualifiedName, namespaceURI, prefix)
1718*cda5da8dSAndroid Build Coastguard Worker        e.ownerDocument = self
1719*cda5da8dSAndroid Build Coastguard Worker        return e
1720*cda5da8dSAndroid Build Coastguard Worker
1721*cda5da8dSAndroid Build Coastguard Worker    def createAttributeNS(self, namespaceURI, qualifiedName):
1722*cda5da8dSAndroid Build Coastguard Worker        prefix, localName = _nssplit(qualifiedName)
1723*cda5da8dSAndroid Build Coastguard Worker        a = Attr(qualifiedName, namespaceURI, localName, prefix)
1724*cda5da8dSAndroid Build Coastguard Worker        a.ownerDocument = self
1725*cda5da8dSAndroid Build Coastguard Worker        a.value = ""
1726*cda5da8dSAndroid Build Coastguard Worker        return a
1727*cda5da8dSAndroid Build Coastguard Worker
1728*cda5da8dSAndroid Build Coastguard Worker    # A couple of implementation-specific helpers to create node types
1729*cda5da8dSAndroid Build Coastguard Worker    # not supported by the W3C DOM specs:
1730*cda5da8dSAndroid Build Coastguard Worker
1731*cda5da8dSAndroid Build Coastguard Worker    def _create_entity(self, name, publicId, systemId, notationName):
1732*cda5da8dSAndroid Build Coastguard Worker        e = Entity(name, publicId, systemId, notationName)
1733*cda5da8dSAndroid Build Coastguard Worker        e.ownerDocument = self
1734*cda5da8dSAndroid Build Coastguard Worker        return e
1735*cda5da8dSAndroid Build Coastguard Worker
1736*cda5da8dSAndroid Build Coastguard Worker    def _create_notation(self, name, publicId, systemId):
1737*cda5da8dSAndroid Build Coastguard Worker        n = Notation(name, publicId, systemId)
1738*cda5da8dSAndroid Build Coastguard Worker        n.ownerDocument = self
1739*cda5da8dSAndroid Build Coastguard Worker        return n
1740*cda5da8dSAndroid Build Coastguard Worker
1741*cda5da8dSAndroid Build Coastguard Worker    def getElementById(self, id):
1742*cda5da8dSAndroid Build Coastguard Worker        if id in self._id_cache:
1743*cda5da8dSAndroid Build Coastguard Worker            return self._id_cache[id]
1744*cda5da8dSAndroid Build Coastguard Worker        if not (self._elem_info or self._magic_id_count):
1745*cda5da8dSAndroid Build Coastguard Worker            return None
1746*cda5da8dSAndroid Build Coastguard Worker
1747*cda5da8dSAndroid Build Coastguard Worker        stack = self._id_search_stack
1748*cda5da8dSAndroid Build Coastguard Worker        if stack is None:
1749*cda5da8dSAndroid Build Coastguard Worker            # we never searched before, or the cache has been cleared
1750*cda5da8dSAndroid Build Coastguard Worker            stack = [self.documentElement]
1751*cda5da8dSAndroid Build Coastguard Worker            self._id_search_stack = stack
1752*cda5da8dSAndroid Build Coastguard Worker        elif not stack:
1753*cda5da8dSAndroid Build Coastguard Worker            # Previous search was completed and cache is still valid;
1754*cda5da8dSAndroid Build Coastguard Worker            # no matching node.
1755*cda5da8dSAndroid Build Coastguard Worker            return None
1756*cda5da8dSAndroid Build Coastguard Worker
1757*cda5da8dSAndroid Build Coastguard Worker        result = None
1758*cda5da8dSAndroid Build Coastguard Worker        while stack:
1759*cda5da8dSAndroid Build Coastguard Worker            node = stack.pop()
1760*cda5da8dSAndroid Build Coastguard Worker            # add child elements to stack for continued searching
1761*cda5da8dSAndroid Build Coastguard Worker            stack.extend([child for child in node.childNodes
1762*cda5da8dSAndroid Build Coastguard Worker                          if child.nodeType in _nodeTypes_with_children])
1763*cda5da8dSAndroid Build Coastguard Worker            # check this node
1764*cda5da8dSAndroid Build Coastguard Worker            info = self._get_elem_info(node)
1765*cda5da8dSAndroid Build Coastguard Worker            if info:
1766*cda5da8dSAndroid Build Coastguard Worker                # We have to process all ID attributes before
1767*cda5da8dSAndroid Build Coastguard Worker                # returning in order to get all the attributes set to
1768*cda5da8dSAndroid Build Coastguard Worker                # be IDs using Element.setIdAttribute*().
1769*cda5da8dSAndroid Build Coastguard Worker                for attr in node.attributes.values():
1770*cda5da8dSAndroid Build Coastguard Worker                    if attr.namespaceURI:
1771*cda5da8dSAndroid Build Coastguard Worker                        if info.isIdNS(attr.namespaceURI, attr.localName):
1772*cda5da8dSAndroid Build Coastguard Worker                            self._id_cache[attr.value] = node
1773*cda5da8dSAndroid Build Coastguard Worker                            if attr.value == id:
1774*cda5da8dSAndroid Build Coastguard Worker                                result = node
1775*cda5da8dSAndroid Build Coastguard Worker                            elif not node._magic_id_nodes:
1776*cda5da8dSAndroid Build Coastguard Worker                                break
1777*cda5da8dSAndroid Build Coastguard Worker                    elif info.isId(attr.name):
1778*cda5da8dSAndroid Build Coastguard Worker                        self._id_cache[attr.value] = node
1779*cda5da8dSAndroid Build Coastguard Worker                        if attr.value == id:
1780*cda5da8dSAndroid Build Coastguard Worker                            result = node
1781*cda5da8dSAndroid Build Coastguard Worker                        elif not node._magic_id_nodes:
1782*cda5da8dSAndroid Build Coastguard Worker                            break
1783*cda5da8dSAndroid Build Coastguard Worker                    elif attr._is_id:
1784*cda5da8dSAndroid Build Coastguard Worker                        self._id_cache[attr.value] = node
1785*cda5da8dSAndroid Build Coastguard Worker                        if attr.value == id:
1786*cda5da8dSAndroid Build Coastguard Worker                            result = node
1787*cda5da8dSAndroid Build Coastguard Worker                        elif node._magic_id_nodes == 1:
1788*cda5da8dSAndroid Build Coastguard Worker                            break
1789*cda5da8dSAndroid Build Coastguard Worker            elif node._magic_id_nodes:
1790*cda5da8dSAndroid Build Coastguard Worker                for attr in node.attributes.values():
1791*cda5da8dSAndroid Build Coastguard Worker                    if attr._is_id:
1792*cda5da8dSAndroid Build Coastguard Worker                        self._id_cache[attr.value] = node
1793*cda5da8dSAndroid Build Coastguard Worker                        if attr.value == id:
1794*cda5da8dSAndroid Build Coastguard Worker                            result = node
1795*cda5da8dSAndroid Build Coastguard Worker            if result is not None:
1796*cda5da8dSAndroid Build Coastguard Worker                break
1797*cda5da8dSAndroid Build Coastguard Worker        return result
1798*cda5da8dSAndroid Build Coastguard Worker
1799*cda5da8dSAndroid Build Coastguard Worker    def getElementsByTagName(self, name):
1800*cda5da8dSAndroid Build Coastguard Worker        return _get_elements_by_tagName_helper(self, name, NodeList())
1801*cda5da8dSAndroid Build Coastguard Worker
1802*cda5da8dSAndroid Build Coastguard Worker    def getElementsByTagNameNS(self, namespaceURI, localName):
1803*cda5da8dSAndroid Build Coastguard Worker        return _get_elements_by_tagName_ns_helper(
1804*cda5da8dSAndroid Build Coastguard Worker            self, namespaceURI, localName, NodeList())
1805*cda5da8dSAndroid Build Coastguard Worker
1806*cda5da8dSAndroid Build Coastguard Worker    def isSupported(self, feature, version):
1807*cda5da8dSAndroid Build Coastguard Worker        return self.implementation.hasFeature(feature, version)
1808*cda5da8dSAndroid Build Coastguard Worker
1809*cda5da8dSAndroid Build Coastguard Worker    def importNode(self, node, deep):
1810*cda5da8dSAndroid Build Coastguard Worker        if node.nodeType == Node.DOCUMENT_NODE:
1811*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.NotSupportedErr("cannot import document nodes")
1812*cda5da8dSAndroid Build Coastguard Worker        elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
1813*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.NotSupportedErr("cannot import document type nodes")
1814*cda5da8dSAndroid Build Coastguard Worker        return _clone_node(node, deep, self)
1815*cda5da8dSAndroid Build Coastguard Worker
1816*cda5da8dSAndroid Build Coastguard Worker    def writexml(self, writer, indent="", addindent="", newl="", encoding=None,
1817*cda5da8dSAndroid Build Coastguard Worker                 standalone=None):
1818*cda5da8dSAndroid Build Coastguard Worker        declarations = []
1819*cda5da8dSAndroid Build Coastguard Worker
1820*cda5da8dSAndroid Build Coastguard Worker        if encoding:
1821*cda5da8dSAndroid Build Coastguard Worker            declarations.append(f'encoding="{encoding}"')
1822*cda5da8dSAndroid Build Coastguard Worker        if standalone is not None:
1823*cda5da8dSAndroid Build Coastguard Worker            declarations.append(f'standalone="{"yes" if standalone else "no"}"')
1824*cda5da8dSAndroid Build Coastguard Worker
1825*cda5da8dSAndroid Build Coastguard Worker        writer.write(f'<?xml version="1.0" {" ".join(declarations)}?>{newl}')
1826*cda5da8dSAndroid Build Coastguard Worker
1827*cda5da8dSAndroid Build Coastguard Worker        for node in self.childNodes:
1828*cda5da8dSAndroid Build Coastguard Worker            node.writexml(writer, indent, addindent, newl)
1829*cda5da8dSAndroid Build Coastguard Worker
1830*cda5da8dSAndroid Build Coastguard Worker    # DOM Level 3 (WD 9 April 2002)
1831*cda5da8dSAndroid Build Coastguard Worker
1832*cda5da8dSAndroid Build Coastguard Worker    def renameNode(self, n, namespaceURI, name):
1833*cda5da8dSAndroid Build Coastguard Worker        if n.ownerDocument is not self:
1834*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.WrongDocumentErr(
1835*cda5da8dSAndroid Build Coastguard Worker                "cannot rename nodes from other documents;\n"
1836*cda5da8dSAndroid Build Coastguard Worker                "expected %s,\nfound %s" % (self, n.ownerDocument))
1837*cda5da8dSAndroid Build Coastguard Worker        if n.nodeType not in (Node.ELEMENT_NODE, Node.ATTRIBUTE_NODE):
1838*cda5da8dSAndroid Build Coastguard Worker            raise xml.dom.NotSupportedErr(
1839*cda5da8dSAndroid Build Coastguard Worker                "renameNode() only applies to element and attribute nodes")
1840*cda5da8dSAndroid Build Coastguard Worker        if namespaceURI != EMPTY_NAMESPACE:
1841*cda5da8dSAndroid Build Coastguard Worker            if ':' in name:
1842*cda5da8dSAndroid Build Coastguard Worker                prefix, localName = name.split(':', 1)
1843*cda5da8dSAndroid Build Coastguard Worker                if (  prefix == "xmlns"
1844*cda5da8dSAndroid Build Coastguard Worker                      and namespaceURI != xml.dom.XMLNS_NAMESPACE):
1845*cda5da8dSAndroid Build Coastguard Worker                    raise xml.dom.NamespaceErr(
1846*cda5da8dSAndroid Build Coastguard Worker                        "illegal use of 'xmlns' prefix")
1847*cda5da8dSAndroid Build Coastguard Worker            else:
1848*cda5da8dSAndroid Build Coastguard Worker                if (  name == "xmlns"
1849*cda5da8dSAndroid Build Coastguard Worker                      and namespaceURI != xml.dom.XMLNS_NAMESPACE
1850*cda5da8dSAndroid Build Coastguard Worker                      and n.nodeType == Node.ATTRIBUTE_NODE):
1851*cda5da8dSAndroid Build Coastguard Worker                    raise xml.dom.NamespaceErr(
1852*cda5da8dSAndroid Build Coastguard Worker                        "illegal use of the 'xmlns' attribute")
1853*cda5da8dSAndroid Build Coastguard Worker                prefix = None
1854*cda5da8dSAndroid Build Coastguard Worker                localName = name
1855*cda5da8dSAndroid Build Coastguard Worker        else:
1856*cda5da8dSAndroid Build Coastguard Worker            prefix = None
1857*cda5da8dSAndroid Build Coastguard Worker            localName = None
1858*cda5da8dSAndroid Build Coastguard Worker        if n.nodeType == Node.ATTRIBUTE_NODE:
1859*cda5da8dSAndroid Build Coastguard Worker            element = n.ownerElement
1860*cda5da8dSAndroid Build Coastguard Worker            if element is not None:
1861*cda5da8dSAndroid Build Coastguard Worker                is_id = n._is_id
1862*cda5da8dSAndroid Build Coastguard Worker                element.removeAttributeNode(n)
1863*cda5da8dSAndroid Build Coastguard Worker        else:
1864*cda5da8dSAndroid Build Coastguard Worker            element = None
1865*cda5da8dSAndroid Build Coastguard Worker        n.prefix = prefix
1866*cda5da8dSAndroid Build Coastguard Worker        n._localName = localName
1867*cda5da8dSAndroid Build Coastguard Worker        n.namespaceURI = namespaceURI
1868*cda5da8dSAndroid Build Coastguard Worker        n.nodeName = name
1869*cda5da8dSAndroid Build Coastguard Worker        if n.nodeType == Node.ELEMENT_NODE:
1870*cda5da8dSAndroid Build Coastguard Worker            n.tagName = name
1871*cda5da8dSAndroid Build Coastguard Worker        else:
1872*cda5da8dSAndroid Build Coastguard Worker            # attribute node
1873*cda5da8dSAndroid Build Coastguard Worker            n.name = name
1874*cda5da8dSAndroid Build Coastguard Worker            if element is not None:
1875*cda5da8dSAndroid Build Coastguard Worker                element.setAttributeNode(n)
1876*cda5da8dSAndroid Build Coastguard Worker                if is_id:
1877*cda5da8dSAndroid Build Coastguard Worker                    element.setIdAttributeNode(n)
1878*cda5da8dSAndroid Build Coastguard Worker        # It's not clear from a semantic perspective whether we should
1879*cda5da8dSAndroid Build Coastguard Worker        # call the user data handlers for the NODE_RENAMED event since
1880*cda5da8dSAndroid Build Coastguard Worker        # we're re-using the existing node.  The draft spec has been
1881*cda5da8dSAndroid Build Coastguard Worker        # interpreted as meaning "no, don't call the handler unless a
1882*cda5da8dSAndroid Build Coastguard Worker        # new node is created."
1883*cda5da8dSAndroid Build Coastguard Worker        return n
1884*cda5da8dSAndroid Build Coastguard Worker
1885*cda5da8dSAndroid Build Coastguard Workerdefproperty(Document, "documentElement",
1886*cda5da8dSAndroid Build Coastguard Worker            doc="Top-level element of this document.")
1887*cda5da8dSAndroid Build Coastguard Worker
1888*cda5da8dSAndroid Build Coastguard Worker
1889*cda5da8dSAndroid Build Coastguard Workerdef _clone_node(node, deep, newOwnerDocument):
1890*cda5da8dSAndroid Build Coastguard Worker    """
1891*cda5da8dSAndroid Build Coastguard Worker    Clone a node and give it the new owner document.
1892*cda5da8dSAndroid Build Coastguard Worker    Called by Node.cloneNode and Document.importNode
1893*cda5da8dSAndroid Build Coastguard Worker    """
1894*cda5da8dSAndroid Build Coastguard Worker    if node.ownerDocument.isSameNode(newOwnerDocument):
1895*cda5da8dSAndroid Build Coastguard Worker        operation = xml.dom.UserDataHandler.NODE_CLONED
1896*cda5da8dSAndroid Build Coastguard Worker    else:
1897*cda5da8dSAndroid Build Coastguard Worker        operation = xml.dom.UserDataHandler.NODE_IMPORTED
1898*cda5da8dSAndroid Build Coastguard Worker    if node.nodeType == Node.ELEMENT_NODE:
1899*cda5da8dSAndroid Build Coastguard Worker        clone = newOwnerDocument.createElementNS(node.namespaceURI,
1900*cda5da8dSAndroid Build Coastguard Worker                                                 node.nodeName)
1901*cda5da8dSAndroid Build Coastguard Worker        for attr in node.attributes.values():
1902*cda5da8dSAndroid Build Coastguard Worker            clone.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value)
1903*cda5da8dSAndroid Build Coastguard Worker            a = clone.getAttributeNodeNS(attr.namespaceURI, attr.localName)
1904*cda5da8dSAndroid Build Coastguard Worker            a.specified = attr.specified
1905*cda5da8dSAndroid Build Coastguard Worker
1906*cda5da8dSAndroid Build Coastguard Worker        if deep:
1907*cda5da8dSAndroid Build Coastguard Worker            for child in node.childNodes:
1908*cda5da8dSAndroid Build Coastguard Worker                c = _clone_node(child, deep, newOwnerDocument)
1909*cda5da8dSAndroid Build Coastguard Worker                clone.appendChild(c)
1910*cda5da8dSAndroid Build Coastguard Worker
1911*cda5da8dSAndroid Build Coastguard Worker    elif node.nodeType == Node.DOCUMENT_FRAGMENT_NODE:
1912*cda5da8dSAndroid Build Coastguard Worker        clone = newOwnerDocument.createDocumentFragment()
1913*cda5da8dSAndroid Build Coastguard Worker        if deep:
1914*cda5da8dSAndroid Build Coastguard Worker            for child in node.childNodes:
1915*cda5da8dSAndroid Build Coastguard Worker                c = _clone_node(child, deep, newOwnerDocument)
1916*cda5da8dSAndroid Build Coastguard Worker                clone.appendChild(c)
1917*cda5da8dSAndroid Build Coastguard Worker
1918*cda5da8dSAndroid Build Coastguard Worker    elif node.nodeType == Node.TEXT_NODE:
1919*cda5da8dSAndroid Build Coastguard Worker        clone = newOwnerDocument.createTextNode(node.data)
1920*cda5da8dSAndroid Build Coastguard Worker    elif node.nodeType == Node.CDATA_SECTION_NODE:
1921*cda5da8dSAndroid Build Coastguard Worker        clone = newOwnerDocument.createCDATASection(node.data)
1922*cda5da8dSAndroid Build Coastguard Worker    elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE:
1923*cda5da8dSAndroid Build Coastguard Worker        clone = newOwnerDocument.createProcessingInstruction(node.target,
1924*cda5da8dSAndroid Build Coastguard Worker                                                             node.data)
1925*cda5da8dSAndroid Build Coastguard Worker    elif node.nodeType == Node.COMMENT_NODE:
1926*cda5da8dSAndroid Build Coastguard Worker        clone = newOwnerDocument.createComment(node.data)
1927*cda5da8dSAndroid Build Coastguard Worker    elif node.nodeType == Node.ATTRIBUTE_NODE:
1928*cda5da8dSAndroid Build Coastguard Worker        clone = newOwnerDocument.createAttributeNS(node.namespaceURI,
1929*cda5da8dSAndroid Build Coastguard Worker                                                   node.nodeName)
1930*cda5da8dSAndroid Build Coastguard Worker        clone.specified = True
1931*cda5da8dSAndroid Build Coastguard Worker        clone.value = node.value
1932*cda5da8dSAndroid Build Coastguard Worker    elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
1933*cda5da8dSAndroid Build Coastguard Worker        assert node.ownerDocument is not newOwnerDocument
1934*cda5da8dSAndroid Build Coastguard Worker        operation = xml.dom.UserDataHandler.NODE_IMPORTED
1935*cda5da8dSAndroid Build Coastguard Worker        clone = newOwnerDocument.implementation.createDocumentType(
1936*cda5da8dSAndroid Build Coastguard Worker            node.name, node.publicId, node.systemId)
1937*cda5da8dSAndroid Build Coastguard Worker        clone.ownerDocument = newOwnerDocument
1938*cda5da8dSAndroid Build Coastguard Worker        if deep:
1939*cda5da8dSAndroid Build Coastguard Worker            clone.entities._seq = []
1940*cda5da8dSAndroid Build Coastguard Worker            clone.notations._seq = []
1941*cda5da8dSAndroid Build Coastguard Worker            for n in node.notations._seq:
1942*cda5da8dSAndroid Build Coastguard Worker                notation = Notation(n.nodeName, n.publicId, n.systemId)
1943*cda5da8dSAndroid Build Coastguard Worker                notation.ownerDocument = newOwnerDocument
1944*cda5da8dSAndroid Build Coastguard Worker                clone.notations._seq.append(notation)
1945*cda5da8dSAndroid Build Coastguard Worker                if hasattr(n, '_call_user_data_handler'):
1946*cda5da8dSAndroid Build Coastguard Worker                    n._call_user_data_handler(operation, n, notation)
1947*cda5da8dSAndroid Build Coastguard Worker            for e in node.entities._seq:
1948*cda5da8dSAndroid Build Coastguard Worker                entity = Entity(e.nodeName, e.publicId, e.systemId,
1949*cda5da8dSAndroid Build Coastguard Worker                                e.notationName)
1950*cda5da8dSAndroid Build Coastguard Worker                entity.actualEncoding = e.actualEncoding
1951*cda5da8dSAndroid Build Coastguard Worker                entity.encoding = e.encoding
1952*cda5da8dSAndroid Build Coastguard Worker                entity.version = e.version
1953*cda5da8dSAndroid Build Coastguard Worker                entity.ownerDocument = newOwnerDocument
1954*cda5da8dSAndroid Build Coastguard Worker                clone.entities._seq.append(entity)
1955*cda5da8dSAndroid Build Coastguard Worker                if hasattr(e, '_call_user_data_handler'):
1956*cda5da8dSAndroid Build Coastguard Worker                    e._call_user_data_handler(operation, e, entity)
1957*cda5da8dSAndroid Build Coastguard Worker    else:
1958*cda5da8dSAndroid Build Coastguard Worker        # Note the cloning of Document and DocumentType nodes is
1959*cda5da8dSAndroid Build Coastguard Worker        # implementation specific.  minidom handles those cases
1960*cda5da8dSAndroid Build Coastguard Worker        # directly in the cloneNode() methods.
1961*cda5da8dSAndroid Build Coastguard Worker        raise xml.dom.NotSupportedErr("Cannot clone node %s" % repr(node))
1962*cda5da8dSAndroid Build Coastguard Worker
1963*cda5da8dSAndroid Build Coastguard Worker    # Check for _call_user_data_handler() since this could conceivably
1964*cda5da8dSAndroid Build Coastguard Worker    # used with other DOM implementations (one of the FourThought
1965*cda5da8dSAndroid Build Coastguard Worker    # DOMs, perhaps?).
1966*cda5da8dSAndroid Build Coastguard Worker    if hasattr(node, '_call_user_data_handler'):
1967*cda5da8dSAndroid Build Coastguard Worker        node._call_user_data_handler(operation, node, clone)
1968*cda5da8dSAndroid Build Coastguard Worker    return clone
1969*cda5da8dSAndroid Build Coastguard Worker
1970*cda5da8dSAndroid Build Coastguard Worker
1971*cda5da8dSAndroid Build Coastguard Workerdef _nssplit(qualifiedName):
1972*cda5da8dSAndroid Build Coastguard Worker    fields = qualifiedName.split(':', 1)
1973*cda5da8dSAndroid Build Coastguard Worker    if len(fields) == 2:
1974*cda5da8dSAndroid Build Coastguard Worker        return fields
1975*cda5da8dSAndroid Build Coastguard Worker    else:
1976*cda5da8dSAndroid Build Coastguard Worker        return (None, fields[0])
1977*cda5da8dSAndroid Build Coastguard Worker
1978*cda5da8dSAndroid Build Coastguard Worker
1979*cda5da8dSAndroid Build Coastguard Workerdef _do_pulldom_parse(func, args, kwargs):
1980*cda5da8dSAndroid Build Coastguard Worker    events = func(*args, **kwargs)
1981*cda5da8dSAndroid Build Coastguard Worker    toktype, rootNode = events.getEvent()
1982*cda5da8dSAndroid Build Coastguard Worker    events.expandNode(rootNode)
1983*cda5da8dSAndroid Build Coastguard Worker    events.clear()
1984*cda5da8dSAndroid Build Coastguard Worker    return rootNode
1985*cda5da8dSAndroid Build Coastguard Worker
1986*cda5da8dSAndroid Build Coastguard Workerdef parse(file, parser=None, bufsize=None):
1987*cda5da8dSAndroid Build Coastguard Worker    """Parse a file into a DOM by filename or file object."""
1988*cda5da8dSAndroid Build Coastguard Worker    if parser is None and not bufsize:
1989*cda5da8dSAndroid Build Coastguard Worker        from xml.dom import expatbuilder
1990*cda5da8dSAndroid Build Coastguard Worker        return expatbuilder.parse(file)
1991*cda5da8dSAndroid Build Coastguard Worker    else:
1992*cda5da8dSAndroid Build Coastguard Worker        from xml.dom import pulldom
1993*cda5da8dSAndroid Build Coastguard Worker        return _do_pulldom_parse(pulldom.parse, (file,),
1994*cda5da8dSAndroid Build Coastguard Worker            {'parser': parser, 'bufsize': bufsize})
1995*cda5da8dSAndroid Build Coastguard Worker
1996*cda5da8dSAndroid Build Coastguard Workerdef parseString(string, parser=None):
1997*cda5da8dSAndroid Build Coastguard Worker    """Parse a file into a DOM from a string."""
1998*cda5da8dSAndroid Build Coastguard Worker    if parser is None:
1999*cda5da8dSAndroid Build Coastguard Worker        from xml.dom import expatbuilder
2000*cda5da8dSAndroid Build Coastguard Worker        return expatbuilder.parseString(string)
2001*cda5da8dSAndroid Build Coastguard Worker    else:
2002*cda5da8dSAndroid Build Coastguard Worker        from xml.dom import pulldom
2003*cda5da8dSAndroid Build Coastguard Worker        return _do_pulldom_parse(pulldom.parseString, (string,),
2004*cda5da8dSAndroid Build Coastguard Worker                                 {'parser': parser})
2005*cda5da8dSAndroid Build Coastguard Worker
2006*cda5da8dSAndroid Build Coastguard Workerdef getDOMImplementation(features=None):
2007*cda5da8dSAndroid Build Coastguard Worker    if features:
2008*cda5da8dSAndroid Build Coastguard Worker        if isinstance(features, str):
2009*cda5da8dSAndroid Build Coastguard Worker            features = domreg._parse_feature_string(features)
2010*cda5da8dSAndroid Build Coastguard Worker        for f, v in features:
2011*cda5da8dSAndroid Build Coastguard Worker            if not Document.implementation.hasFeature(f, v):
2012*cda5da8dSAndroid Build Coastguard Worker                return None
2013*cda5da8dSAndroid Build Coastguard Worker    return Document.implementation
2014