Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

dom.py 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. from __future__ import absolute_import, division, unicode_literals
  2. from collections import MutableMapping
  3. from xml.dom import minidom, Node
  4. import weakref
  5. from . import base
  6. from .. import constants
  7. from ..constants import namespaces
  8. from .._utils import moduleFactoryFactory
  9. def getDomBuilder(DomImplementation):
  10. Dom = DomImplementation
  11. class AttrList(MutableMapping):
  12. def __init__(self, element):
  13. self.element = element
  14. def __iter__(self):
  15. return iter(self.element.attributes.keys())
  16. def __setitem__(self, name, value):
  17. if isinstance(name, tuple):
  18. raise NotImplementedError
  19. else:
  20. attr = self.element.ownerDocument.createAttribute(name)
  21. attr.value = value
  22. self.element.attributes[name] = attr
  23. def __len__(self):
  24. return len(self.element.attributes)
  25. def items(self):
  26. return list(self.element.attributes.items())
  27. def values(self):
  28. return list(self.element.attributes.values())
  29. def __getitem__(self, name):
  30. if isinstance(name, tuple):
  31. raise NotImplementedError
  32. else:
  33. return self.element.attributes[name].value
  34. def __delitem__(self, name):
  35. if isinstance(name, tuple):
  36. raise NotImplementedError
  37. else:
  38. del self.element.attributes[name]
  39. class NodeBuilder(base.Node):
  40. def __init__(self, element):
  41. base.Node.__init__(self, element.nodeName)
  42. self.element = element
  43. namespace = property(lambda self: hasattr(self.element, "namespaceURI") and
  44. self.element.namespaceURI or None)
  45. def appendChild(self, node):
  46. node.parent = self
  47. self.element.appendChild(node.element)
  48. def insertText(self, data, insertBefore=None):
  49. text = self.element.ownerDocument.createTextNode(data)
  50. if insertBefore:
  51. self.element.insertBefore(text, insertBefore.element)
  52. else:
  53. self.element.appendChild(text)
  54. def insertBefore(self, node, refNode):
  55. self.element.insertBefore(node.element, refNode.element)
  56. node.parent = self
  57. def removeChild(self, node):
  58. if node.element.parentNode == self.element:
  59. self.element.removeChild(node.element)
  60. node.parent = None
  61. def reparentChildren(self, newParent):
  62. while self.element.hasChildNodes():
  63. child = self.element.firstChild
  64. self.element.removeChild(child)
  65. newParent.element.appendChild(child)
  66. self.childNodes = []
  67. def getAttributes(self):
  68. return AttrList(self.element)
  69. def setAttributes(self, attributes):
  70. if attributes:
  71. for name, value in list(attributes.items()):
  72. if isinstance(name, tuple):
  73. if name[0] is not None:
  74. qualifiedName = (name[0] + ":" + name[1])
  75. else:
  76. qualifiedName = name[1]
  77. self.element.setAttributeNS(name[2], qualifiedName,
  78. value)
  79. else:
  80. self.element.setAttribute(
  81. name, value)
  82. attributes = property(getAttributes, setAttributes)
  83. def cloneNode(self):
  84. return NodeBuilder(self.element.cloneNode(False))
  85. def hasContent(self):
  86. return self.element.hasChildNodes()
  87. def getNameTuple(self):
  88. if self.namespace is None:
  89. return namespaces["html"], self.name
  90. else:
  91. return self.namespace, self.name
  92. nameTuple = property(getNameTuple)
  93. class TreeBuilder(base.TreeBuilder): # pylint:disable=unused-variable
  94. def documentClass(self):
  95. self.dom = Dom.getDOMImplementation().createDocument(None, None, None)
  96. return weakref.proxy(self)
  97. def insertDoctype(self, token):
  98. name = token["name"]
  99. publicId = token["publicId"]
  100. systemId = token["systemId"]
  101. domimpl = Dom.getDOMImplementation()
  102. doctype = domimpl.createDocumentType(name, publicId, systemId)
  103. self.document.appendChild(NodeBuilder(doctype))
  104. if Dom == minidom:
  105. doctype.ownerDocument = self.dom
  106. def elementClass(self, name, namespace=None):
  107. if namespace is None and self.defaultNamespace is None:
  108. node = self.dom.createElement(name)
  109. else:
  110. node = self.dom.createElementNS(namespace, name)
  111. return NodeBuilder(node)
  112. def commentClass(self, data):
  113. return NodeBuilder(self.dom.createComment(data))
  114. def fragmentClass(self):
  115. return NodeBuilder(self.dom.createDocumentFragment())
  116. def appendChild(self, node):
  117. self.dom.appendChild(node.element)
  118. def testSerializer(self, element):
  119. return testSerializer(element)
  120. def getDocument(self):
  121. return self.dom
  122. def getFragment(self):
  123. return base.TreeBuilder.getFragment(self).element
  124. def insertText(self, data, parent=None):
  125. data = data
  126. if parent != self:
  127. base.TreeBuilder.insertText(self, data, parent)
  128. else:
  129. # HACK: allow text nodes as children of the document node
  130. if hasattr(self.dom, '_child_node_types'):
  131. # pylint:disable=protected-access
  132. if Node.TEXT_NODE not in self.dom._child_node_types:
  133. self.dom._child_node_types = list(self.dom._child_node_types)
  134. self.dom._child_node_types.append(Node.TEXT_NODE)
  135. self.dom.appendChild(self.dom.createTextNode(data))
  136. implementation = DomImplementation
  137. name = None
  138. def testSerializer(element):
  139. element.normalize()
  140. rv = []
  141. def serializeElement(element, indent=0):
  142. if element.nodeType == Node.DOCUMENT_TYPE_NODE:
  143. if element.name:
  144. if element.publicId or element.systemId:
  145. publicId = element.publicId or ""
  146. systemId = element.systemId or ""
  147. rv.append("""|%s<!DOCTYPE %s "%s" "%s">""" %
  148. (' ' * indent, element.name, publicId, systemId))
  149. else:
  150. rv.append("|%s<!DOCTYPE %s>" % (' ' * indent, element.name))
  151. else:
  152. rv.append("|%s<!DOCTYPE >" % (' ' * indent,))
  153. elif element.nodeType == Node.DOCUMENT_NODE:
  154. rv.append("#document")
  155. elif element.nodeType == Node.DOCUMENT_FRAGMENT_NODE:
  156. rv.append("#document-fragment")
  157. elif element.nodeType == Node.COMMENT_NODE:
  158. rv.append("|%s<!-- %s -->" % (' ' * indent, element.nodeValue))
  159. elif element.nodeType == Node.TEXT_NODE:
  160. rv.append("|%s\"%s\"" % (' ' * indent, element.nodeValue))
  161. else:
  162. if (hasattr(element, "namespaceURI") and
  163. element.namespaceURI is not None):
  164. name = "%s %s" % (constants.prefixes[element.namespaceURI],
  165. element.nodeName)
  166. else:
  167. name = element.nodeName
  168. rv.append("|%s<%s>" % (' ' * indent, name))
  169. if element.hasAttributes():
  170. attributes = []
  171. for i in range(len(element.attributes)):
  172. attr = element.attributes.item(i)
  173. name = attr.nodeName
  174. value = attr.value
  175. ns = attr.namespaceURI
  176. if ns:
  177. name = "%s %s" % (constants.prefixes[ns], attr.localName)
  178. else:
  179. name = attr.nodeName
  180. attributes.append((name, value))
  181. for name, value in sorted(attributes):
  182. rv.append('|%s%s="%s"' % (' ' * (indent + 2), name, value))
  183. indent += 2
  184. for child in element.childNodes:
  185. serializeElement(child, indent)
  186. serializeElement(element, 0)
  187. return "\n".join(rv)
  188. return locals()
  189. # The actual means to get a module!
  190. getDomModule = moduleFactoryFactory(getDomBuilder)