| OLD | NEW |
| (Empty) |
| 1 # -*- test-case-name: twisted.web.test.test_woven -*- | |
| 2 # Copyright (c) 2001-2004 Twisted Matrix Laboratories. | |
| 3 # See LICENSE for details. | |
| 4 | |
| 5 # | |
| 6 | |
| 7 from __future__ import nested_scopes | |
| 8 | |
| 9 from twisted.web import microdom | |
| 10 from microdom import getElementsByTagName, escape, unescape | |
| 11 | |
| 12 try: | |
| 13 import cStringIO as StringIO | |
| 14 except ImportError: | |
| 15 import StringIO | |
| 16 | |
| 17 class NodeLookupError(Exception): pass | |
| 18 | |
| 19 | |
| 20 def substitute(request, node, subs): | |
| 21 """ | |
| 22 Look through the given node's children for strings, and | |
| 23 attempt to do string substitution with the given parameter. | |
| 24 """ | |
| 25 for child in node.childNodes: | |
| 26 if hasattr(child, 'nodeValue') and child.nodeValue: | |
| 27 child.replaceData(0, len(child.nodeValue), child.nodeValue % subs) | |
| 28 substitute(request, child, subs) | |
| 29 | |
| 30 def _get(node, nodeId, nodeAttrs=('id','class','model','pattern')): | |
| 31 """ | |
| 32 (internal) Get a node with the specified C{nodeId} as any of the C{class}, | |
| 33 C{id} or C{pattern} attributes. | |
| 34 """ | |
| 35 | |
| 36 if hasattr(node, 'hasAttributes') and node.hasAttributes(): | |
| 37 for nodeAttr in nodeAttrs: | |
| 38 if (str (node.getAttribute(nodeAttr)) == nodeId): | |
| 39 return node | |
| 40 if node.hasChildNodes(): | |
| 41 if hasattr(node.childNodes, 'length'): | |
| 42 length = node.childNodes.length | |
| 43 else: | |
| 44 length = len(node.childNodes) | |
| 45 for childNum in range(length): | |
| 46 result = _get(node.childNodes[childNum], nodeId) | |
| 47 if result: return result | |
| 48 | |
| 49 def get(node, nodeId): | |
| 50 """ | |
| 51 Get a node with the specified C{nodeId} as any of the C{class}, | |
| 52 C{id} or C{pattern} attributes. If there is no such node, raise | |
| 53 L{NodeLookupError}. | |
| 54 """ | |
| 55 result = _get(node, nodeId) | |
| 56 if result: return result | |
| 57 raise NodeLookupError, nodeId | |
| 58 | |
| 59 def getIfExists(node, nodeId): | |
| 60 """ | |
| 61 Get a node with the specified C{nodeId} as any of the C{class}, | |
| 62 C{id} or C{pattern} attributes. If there is no such node, return | |
| 63 C{None}. | |
| 64 """ | |
| 65 return _get(node, nodeId) | |
| 66 | |
| 67 def getAndClear(node, nodeId): | |
| 68 """Get a node with the specified C{nodeId} as any of the C{class}, | |
| 69 C{id} or C{pattern} attributes. If there is no such node, raise | |
| 70 L{NodeLookupError}. Remove all child nodes before returning. | |
| 71 """ | |
| 72 result = get(node, nodeId) | |
| 73 if result: | |
| 74 clearNode(result) | |
| 75 return result | |
| 76 | |
| 77 def clearNode(node): | |
| 78 """ | |
| 79 Remove all children from the given node. | |
| 80 """ | |
| 81 node.childNodes[:] = [] | |
| 82 | |
| 83 def locateNodes(nodeList, key, value, noNesting=1): | |
| 84 """ | |
| 85 Find subnodes in the given node where the given attribute | |
| 86 has the given value. | |
| 87 """ | |
| 88 returnList = [] | |
| 89 if not isinstance(nodeList, type([])): | |
| 90 return locateNodes(nodeList.childNodes, key, value, noNesting) | |
| 91 for childNode in nodeList: | |
| 92 if not hasattr(childNode, 'getAttribute'): | |
| 93 continue | |
| 94 if str(childNode.getAttribute(key)) == value: | |
| 95 returnList.append(childNode) | |
| 96 if noNesting: | |
| 97 continue | |
| 98 returnList.extend(locateNodes(childNode, key, value, noNesting)) | |
| 99 return returnList | |
| 100 | |
| 101 def superSetAttribute(node, key, value): | |
| 102 if not hasattr(node, 'setAttribute'): return | |
| 103 node.setAttribute(key, value) | |
| 104 if node.hasChildNodes(): | |
| 105 for child in node.childNodes: | |
| 106 superSetAttribute(child, key, value) | |
| 107 | |
| 108 def superPrependAttribute(node, key, value): | |
| 109 if not hasattr(node, 'setAttribute'): return | |
| 110 old = node.getAttribute(key) | |
| 111 if old: | |
| 112 node.setAttribute(key, value+'/'+old) | |
| 113 else: | |
| 114 node.setAttribute(key, value) | |
| 115 if node.hasChildNodes(): | |
| 116 for child in node.childNodes: | |
| 117 superPrependAttribute(child, key, value) | |
| 118 | |
| 119 def superAppendAttribute(node, key, value): | |
| 120 if not hasattr(node, 'setAttribute'): return | |
| 121 old = node.getAttribute(key) | |
| 122 if old: | |
| 123 node.setAttribute(key, old + '/' + value) | |
| 124 else: | |
| 125 node.setAttribute(key, value) | |
| 126 if node.hasChildNodes(): | |
| 127 for child in node.childNodes: | |
| 128 superAppendAttribute(child, key, value) | |
| 129 | |
| 130 def gatherTextNodes(iNode, dounescape=0, joinWith=""): | |
| 131 """Visit each child node and collect its text data, if any, into a string. | |
| 132 For example:: | |
| 133 >>> doc=microdom.parseString('<a>1<b>2<c>3</c>4</b></a>') | |
| 134 >>> gatherTextNodes(doc.documentElement) | |
| 135 '1234' | |
| 136 With dounescape=1, also convert entities back into normal characters. | |
| 137 @return: the gathered nodes as a single string | |
| 138 @rtype: str | |
| 139 """ | |
| 140 gathered=[] | |
| 141 gathered_append=gathered.append | |
| 142 slice=[iNode] | |
| 143 while len(slice)>0: | |
| 144 c=slice.pop(0) | |
| 145 if hasattr(c, 'nodeValue') and c.nodeValue is not None: | |
| 146 if dounescape: | |
| 147 val=unescape(c.nodeValue) | |
| 148 else: | |
| 149 val=c.nodeValue | |
| 150 gathered_append(val) | |
| 151 slice[:0]=c.childNodes | |
| 152 return joinWith.join(gathered) | |
| 153 | |
| 154 class RawText(microdom.Text): | |
| 155 """This is an evil and horrible speed hack. Basically, if you have a big | |
| 156 chunk of XML that you want to insert into the DOM, but you don't want to | |
| 157 incur the cost of parsing it, you can construct one of these and insert it | |
| 158 into the DOM. This will most certainly only work with microdom as the API | |
| 159 for converting nodes to xml is different in every DOM implementation. | |
| 160 | |
| 161 This could be improved by making this class a Lazy parser, so if you | |
| 162 inserted this into the DOM and then later actually tried to mutate this | |
| 163 node, it would be parsed then. | |
| 164 """ | |
| 165 | |
| 166 def writexml(self, writer, indent="", addindent="", newl="", strip=0, nspref
ixes=None, namespace=None): | |
| 167 writer.write("%s%s%s" % (indent, self.data, newl)) | |
| 168 | |
| 169 def findNodes(parent, matcher, accum=None): | |
| 170 if accum is None: | |
| 171 accum = [] | |
| 172 if not parent.hasChildNodes(): | |
| 173 return accum | |
| 174 for child in parent.childNodes: | |
| 175 # print child, child.nodeType, child.nodeName | |
| 176 if matcher(child): | |
| 177 accum.append(child) | |
| 178 findNodes(child, matcher, accum) | |
| 179 return accum | |
| 180 | |
| 181 | |
| 182 def findNodesShallowOnMatch(parent, matcher, recurseMatcher, accum=None): | |
| 183 if accum is None: | |
| 184 accum = [] | |
| 185 if not parent.hasChildNodes(): | |
| 186 return accum | |
| 187 for child in parent.childNodes: | |
| 188 # print child, child.nodeType, child.nodeName | |
| 189 if matcher(child): | |
| 190 accum.append(child) | |
| 191 if recurseMatcher(child): | |
| 192 findNodesShallowOnMatch(child, matcher, recurseMatcher, accum) | |
| 193 return accum | |
| 194 | |
| 195 def findNodesShallow(parent, matcher, accum=None): | |
| 196 if accum is None: | |
| 197 accum = [] | |
| 198 if not parent.hasChildNodes(): | |
| 199 return accum | |
| 200 for child in parent.childNodes: | |
| 201 if matcher(child): | |
| 202 accum.append(child) | |
| 203 else: | |
| 204 findNodes(child, matcher, accum) | |
| 205 return accum | |
| 206 | |
| 207 | |
| 208 def findElementsWithAttributeShallow(parent, attribute): | |
| 209 return findNodesShallow(parent, | |
| 210 lambda n: isinstance(n, microdom.Element) and | |
| 211 n.hasAttribute(attribute)) | |
| 212 | |
| 213 | |
| 214 def findElements(parent, matcher): | |
| 215 return findNodes( | |
| 216 parent, | |
| 217 lambda n, matcher=matcher: isinstance(n, microdom.Element) and | |
| 218 matcher(n)) | |
| 219 | |
| 220 def findElementsWithAttribute(parent, attribute, value=None): | |
| 221 if value: | |
| 222 return findElements( | |
| 223 parent, | |
| 224 lambda n, attribute=attribute, value=value: | |
| 225 n.hasAttribute(attribute) and n.getAttribute(attribute) == value) | |
| 226 else: | |
| 227 return findElements( | |
| 228 parent, | |
| 229 lambda n, attribute=attribute: n.hasAttribute(attribute)) | |
| 230 | |
| 231 | |
| 232 def findNodesNamed(parent, name): | |
| 233 return findNodes(parent, lambda n, name=name: n.nodeName == name) | |
| 234 | |
| 235 | |
| 236 def writeNodeData(node, oldio): | |
| 237 for subnode in node.childNodes: | |
| 238 if hasattr(subnode, 'data'): | |
| 239 oldio.write(str(subnode.data)) | |
| 240 else: | |
| 241 writeNodeData(subnode, oldio) | |
| 242 | |
| 243 | |
| 244 def getNodeText(node): | |
| 245 oldio = StringIO.StringIO() | |
| 246 writeNodeData(node, oldio) | |
| 247 return oldio.getvalue() | |
| 248 | |
| 249 def getParents(node): | |
| 250 l = [] | |
| 251 while node: | |
| 252 l.append(node) | |
| 253 node = node.parentNode | |
| 254 return l | |
| 255 | |
| 256 def namedChildren(parent, nodeName): | |
| 257 """namedChildren(parent, nodeName) -> children (not descendants) of parent | |
| 258 that have tagName == nodeName | |
| 259 """ | |
| 260 return [n for n in parent.childNodes if getattr(n, 'tagName', '')==nodeName] | |
| OLD | NEW |