~justin-fathomdb/nova/justinsb-openstack-api-volumes

« back to all changes in this revision

Viewing changes to vendor/Twisted-10.0.0/twisted/web/domhelpers.py

  • Committer: Jesse Andrews
  • Date: 2010-05-28 06:05:26 UTC
  • Revision ID: git-v1:bf6e6e718cdc7488e2da87b21e258ccc065fe499
initial commit

Show diffs side-by-side

added added

removed removed

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