ยปCore Development>Code coverage>Lib/xml/dom/minidom.py

Python code coverage for Lib/xml/dom/minidom.py

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