1 class Element:
2 """An XML element.
3
4 This class is the reference implementation of the Element interface.
5
6 An element's length is its number of subelements. That means if you
7 want to check if an element is truly empty, you should check BOTH
8 its length AND its text attribute.
9
10 The element tag, attribute names, and attribute values can be either
11 bytes or strings.
12
13 *tag* is the element name. *attrib* is an optional dictionary containing
14 element attributes. *extra* are additional element attributes given as
15 keyword arguments.
16
17 Example form:
18 <tag attrib>text<child/>...</tag>tail
19
20 """
21
22 當前節點的標籤名
23 tag = None
24 """The element's name."""
25
26 當前節點的屬性
27
28 attrib = None
29 """Dictionary of the element's attributes."""
30
31 當前節點的內容
32 text = None
33 """
34 Text before first subelement. This is either a string or the value None.
35 Note that if there is no text, this attribute may be either
36 None or the empty string, depending on the parser.
37
38 """
39
40 tail = None
41 """
42 Text after this element's end tag, but before the next sibling element's
43 start tag. This is either a string or the value None. Note that if there
44 was no text, this attribute may be either None or an empty string,
45 depending on the parser.
46
47 """
48
49 def __init__(self, tag, attrib={}, **extra):
50 if not isinstance(attrib, dict):
51 raise TypeError("attrib must be dict, not %s" % (
52 attrib.__class__.__name__,))
53 attrib = attrib.copy()
54 attrib.update(extra)
55 self.tag = tag
56 self.attrib = attrib
57 self._children = []
58
59 def __repr__(self):
60 return "<%s %r at %#x>" % (self.__class__.__name__, self.tag, id(self))
61
62 def makeelement(self, tag, attrib):
63 建立一個新節點
64 """Create a new element with the same type.
65
66 *tag* is a string containing the element name.
67 *attrib* is a dictionary containing the element attributes.
68
69 Do not call this method, use the SubElement factory function instead.
70
71 """
72 return self.__class__(tag, attrib)
73
74 def copy(self):
75 """Return copy of current element.
76
77 This creates a shallow copy. Subelements will be shared with the
78 original tree.
79
80 """
81 elem = self.makeelement(self.tag, self.attrib)
82 elem.text = self.text
83 elem.tail = self.tail
84 elem[:] = self
85 return elem
86
87 def __len__(self):
88 return len(self._children)
89
90 def __bool__(self):
91 warnings.warn(
92 "The behavior of this method will change in future versions. "
93 "Use specific 'len(elem)' or 'elem is not None' test instead.",
94 FutureWarning, stacklevel=2
95 )
96 return len(self._children) != 0 # emulate old behaviour, for now
97
98 def __getitem__(self, index):
99 return self._children[index]
100
101 def __setitem__(self, index, element):
102 # if isinstance(index, slice):
103 # for elt in element:
104 # assert iselement(elt)
105 # else:
106 # assert iselement(element)
107 self._children[index] = element
108
109 def __delitem__(self, index):
110 del self._children[index]
111
112 def append(self, subelement):
113 爲當前節點追加一個子節點
114 """Add *subelement* to the end of this element.
115
116 The new element will appear in document order after the last existing
117 subelement (or directly after the text, if it's the first subelement),
118 but before the end tag for this element.
119
120 """
121 self._assert_is_element(subelement)
122 self._children.append(subelement)
123
124 def extend(self, elements):
125 爲當前節點擴展 n 個子節點
126 """Append subelements from a sequence.
127
128 *elements* is a sequence with zero or more elements.
129
130 """
131 for element in elements:
132 self._assert_is_element(element)
133 self._children.extend(elements)
134
135 def insert(self, index, subelement):
136 在當前節點的子節點中插入某個節點,即:爲當前節點建立子節點,而後插入指定位置
137 """Insert *subelement* at position *index*."""
138 self._assert_is_element(subelement)
139 self._children.insert(index, subelement)
140
141 def _assert_is_element(self, e):
142 # Need to refer to the actual Python implementation, not the
143 # shadowing C implementation.
144 if not isinstance(e, _Element_Py):
145 raise TypeError('expected an Element, not %s' % type(e).__name__)
146
147 def remove(self, subelement):
148 在當前節點在子節點中刪除某個節點
149 """Remove matching subelement.
150
151 Unlike the find methods, this method compares elements based on
152 identity, NOT ON tag value or contents. To remove subelements by
153 other means, the easiest way is to use a list comprehension to
154 select what elements to keep, and then use slice assignment to update
155 the parent element.
156
157 ValueError is raised if a matching element could not be found.
158
159 """
160 # assert iselement(element)
161 self._children.remove(subelement)
162
163 def getchildren(self):
164 獲取全部的子節點(廢棄)
165 """(Deprecated) Return all subelements.
166
167 Elements are returned in document order.
168
169 """
170 warnings.warn(
171 "This method will be removed in future versions. "
172 "Use 'list(elem)' or iteration over elem instead.",
173 DeprecationWarning, stacklevel=2
174 )
175 return self._children
176
177 def find(self, path, namespaces=None):
178 獲取第一個尋找到的子節點
179 """Find first matching element by tag name or path.
180
181 *path* is a string having either an element tag or an XPath,
182 *namespaces* is an optional mapping from namespace prefix to full name.
183
184 Return the first matching element, or None if no element was found.
185
186 """
187 return ElementPath.find(self, path, namespaces)
188
189 def findtext(self, path, default=None, namespaces=None):
190 獲取第一個尋找到的子節點的內容
191 """Find text for first matching element by tag name or path.
192
193 *path* is a string having either an element tag or an XPath,
194 *default* is the value to return if the element was not found,
195 *namespaces* is an optional mapping from namespace prefix to full name.
196
197 Return text content of first matching element, or default value if
198 none was found. Note that if an element is found having no text
199 content, the empty string is returned.
200
201 """
202 return ElementPath.findtext(self, path, default, namespaces)
203
204 def findall(self, path, namespaces=None):
205 獲取全部的子節點
206 """Find all matching subelements by tag name or path.
207
208 *path* is a string having either an element tag or an XPath,
209 *namespaces* is an optional mapping from namespace prefix to full name.
210
211 Returns list containing all matching elements in document order.
212
213 """
214 return ElementPath.findall(self, path, namespaces)
215
216 def iterfind(self, path, namespaces=None):
217 獲取全部指定的節點,並建立一個迭代器(能夠被for循環)
218 """Find all matching subelements by tag name or path.
219
220 *path* is a string having either an element tag or an XPath,
221 *namespaces* is an optional mapping from namespace prefix to full name.
222
223 Return an iterable yielding all matching elements in document order.
224
225 """
226 return ElementPath.iterfind(self, path, namespaces)
227
228 def clear(self):
229 清空節點
230 """Reset element.
231
232 This function removes all subelements, clears all attributes, and sets
233 the text and tail attributes to None.
234
235 """
236 self.attrib.clear()
237 self._children = []
238 self.text = self.tail = None
239
240 def get(self, key, default=None):
241 獲取當前節點的屬性值
242 """Get element attribute.
243
244 Equivalent to attrib.get, but some implementations may handle this a
245 bit more efficiently. *key* is what attribute to look for, and
246 *default* is what to return if the attribute was not found.
247
248 Returns a string containing the attribute value, or the default if
249 attribute was not found.
250
251 """
252 return self.attrib.get(key, default)
253
254 def set(self, key, value):
255 爲當前節點設置屬性值
256 """Set element attribute.
257
258 Equivalent to attrib[key] = value, but some implementations may handle
259 this a bit more efficiently. *key* is what attribute to set, and
260 *value* is the attribute value to set it to.
261
262 """
263 self.attrib[key] = value
264
265 def keys(self):
266 獲取當前節點的全部屬性的 key
267
268 """Get list of attribute names.
269
270 Names are returned in an arbitrary order, just like an ordinary
271 Python dict. Equivalent to attrib.keys()
272
273 """
274 return self.attrib.keys()
275
276 def items(self):
277 獲取當前節點的全部屬性值,每一個屬性都是一個鍵值對
278 """Get element attributes as a sequence.
279
280 The attributes are returned in arbitrary order. Equivalent to
281 attrib.items().
282
283 Return a list of (name, value) tuples.
284
285 """
286 return self.attrib.items()
287
288 def iter(self, tag=None):
289 在當前節點的子孫中根據節點名稱尋找全部指定的節點,並返回一個迭代器(能夠被for循環)。
290 """Create tree iterator.
291
292 The iterator loops over the element and all subelements in document
293 order, returning all elements with a matching tag.
294
295 If the tree structure is modified during iteration, new or removed
296 elements may or may not be included. To get a stable set, use the
297 list() function on the iterator, and loop over the resulting list.
298
299 *tag* is what tags to look for (default is to return all elements)
300
301 Return an iterator containing all the matching elements.
302
303 """
304 if tag == "*":
305 tag = None
306 if tag is None or self.tag == tag:
307 yield self
308 for e in self._children:
309 yield from e.iter(tag)
310
311 # compatibility
312 def getiterator(self, tag=None):
313 # Change for a DeprecationWarning in 1.4
314 warnings.warn(
315 "This method will be removed in future versions. "
316 "Use 'elem.iter()' or 'list(elem.iter())' instead.",
317 PendingDeprecationWarning, stacklevel=2
318 )
319 return list(self.iter(tag))
320
321 def itertext(self):
322 在當前節點的子孫中根據節點名稱尋找全部指定的節點的內容,並返回一個迭代器(能夠被for循環)。
323 """Create text iterator.
324
325 The iterator loops over the element and all subelements in document
326 order, returning all inner text.
327
328 """
329 tag = self.tag
330 if not isinstance(tag, str) and tag is not None:
331 return
332 if self.text:
333 yield self.text
334 for e in self:
335 yield from e.itertext()
336 if e.tail:
337 yield e.tail