|
1 | | -try: |
2 | | - from xml.etree import ElementTree |
3 | | -except ImportError: |
4 | | - from elementtree import ElementTree |
| 1 | +import etreefull |
5 | 2 |
|
6 | | -import _base |
7 | | - |
8 | | -class Element(_base.Node): |
9 | | - def __init__(self, name): |
10 | | - self._element = ElementTree.Element(name) |
11 | | - self.name = name |
12 | | - self.parent = None |
13 | | - self._childNodes = [] |
14 | | - self._flags = [] |
15 | | - |
16 | | - def _setName(self, name): |
17 | | - self._element.tag = name |
18 | | - |
19 | | - def _getName(self): |
20 | | - return self._element.tag |
21 | | - |
22 | | - name = property(_getName, _setName) |
23 | | - |
24 | | - def _getAttributes(self): |
25 | | - return self._element.attrib |
26 | | - |
27 | | - def _setAttributes(self, attributes): |
28 | | - #Delete existing attributes first |
29 | | - #XXX - there may be a better way to do this... |
30 | | - for key in self._element.attrib.keys(): |
31 | | - del self._element.attrib[key] |
32 | | - for key, value in attributes.iteritems(): |
33 | | - self._element.set(key, value) |
34 | | - |
35 | | - attributes = property(_getAttributes, _setAttributes) |
36 | | - |
37 | | - def _getChildNodes(self): |
38 | | - return self._childNodes |
39 | | - |
40 | | - def _setChildNodes(self, value): |
41 | | - del self._element[:] |
42 | | - self._childNodes = [] |
43 | | - for element in value: |
44 | | - self.insertChild(element) |
45 | | - |
46 | | - childNodes = property(_getChildNodes, _setChildNodes) |
47 | | - |
48 | | - def hasContent(self): |
49 | | - """Return true if the node has children or text""" |
50 | | - return bool(self._element.text or self._element.getchildren()) |
51 | | - |
52 | | - def appendChild(self, node): |
53 | | - self._childNodes.append(node) |
54 | | - self._element.append(node._element) |
55 | | - node.parent = self |
56 | | - |
57 | | - def insertBefore(self, node, refNode): |
58 | | - index = self._element.getchildren().index(refNode._element) |
59 | | - self._element.insert(index, node._element) |
60 | | - node.parent = self |
61 | | - |
62 | | - def removeChild(self, node): |
63 | | - self._element.remove(node._element) |
64 | | - node.parent=None |
65 | | - |
66 | | - def insertText(self, data, insertBefore=None): |
67 | | - if not(len(self._element)): |
68 | | - if not self._element.text: |
69 | | - self._element.text = "" |
70 | | - self._element.text += data |
71 | | - elif insertBefore is None: |
72 | | - #Insert the text as the tail of the last child element |
73 | | - if not self._element[-1].tail: |
74 | | - self._element[-1].tail = "" |
75 | | - self._element[-1].tail += data |
76 | | - else: |
77 | | - #Insert the text before the specified node |
78 | | - children = self._element.getchildren() |
79 | | - index = children.index(insertBefore._element) |
80 | | - if index > 0: |
81 | | - if not self._element[index-1].tail: |
82 | | - self._element[index-1].tail = "" |
83 | | - self._element[index-1].tail += data |
84 | | - else: |
85 | | - if not self._element.text: |
86 | | - self._element.text = "" |
87 | | - self._element.text += data |
88 | | - |
89 | | - def cloneNode(self): |
90 | | - element = Element(self.name) |
91 | | - element.attributes = self.attributes |
92 | | - return element |
93 | | - |
94 | | - def reparentChildren(self, newParent): |
95 | | - if newParent.childNodes: |
96 | | - newParent.childNodes[-1]._element.tail += self._element.text |
97 | | - else: |
98 | | - if not newParent._element.text: |
99 | | - newParent._element.text = "" |
100 | | - if self._element.text is not None: |
101 | | - newParent._element.text += self._element.text |
102 | | - self._element.text = "" |
103 | | - _base.Node.reparentChildren(self, newParent) |
104 | | - |
105 | | -class Comment(Element): |
106 | | - def __init__(self, data): |
107 | | - #Use the superclass constructor to set all properties on the |
108 | | - #wrapper element |
109 | | - Element.__init__(self, None) |
110 | | - self._element = ElementTree.Comment(data) |
111 | | - |
112 | | - def _getData(self): |
113 | | - return self._element.text |
114 | | - |
115 | | - def _setData(self, value): |
116 | | - self._element.text = value |
117 | | - |
118 | | - data = property(_getData, _setData) |
119 | | - |
120 | | -class DocumentType(Element): |
121 | | - def __init__(self, name): |
122 | | - Element.__init__(self, DocumentType) |
123 | | - self._element.text = name |
124 | | - |
125 | | -class Document(Element): |
126 | | - def __init__(self): |
127 | | - Element.__init__(self, Document) |
128 | | - |
129 | | -def testSerializer(element): |
130 | | - rv = [] |
131 | | - finalText = None |
132 | | - def serializeElement(element, indent=0): |
133 | | - if element.tag is DocumentType: |
134 | | - rv.append("|%s<!DOCTYPE %s>"%(' '*indent, element.text)) |
135 | | - elif element.tag is Document: |
136 | | - rv.append("#document") |
137 | | - if element.text: |
138 | | - rv.append("|%s\"%s\""%(' '*(indent+2), element.text)) |
139 | | - if element.tail: |
140 | | - finalText = element.tail |
141 | | - elif element.tag is ElementTree.Comment: |
142 | | - rv.append("|%s<!-- %s -->"%(' '*indent, element.text)) |
143 | | - else: |
144 | | - rv.append("|%s<%s>"%(' '*indent, element.tag)) |
145 | | - if hasattr(element, "attrib"): |
146 | | - for name, value in element.attrib.iteritems(): |
147 | | - rv.append('|%s%s="%s"' % (' '*(indent+2), name, value)) |
148 | | - if element.text: |
149 | | - rv.append("|%s\"%s\"" %(' '*(indent+2), element.text)) |
150 | | - indent += 2 |
151 | | - for child in element.getchildren(): |
152 | | - serializeElement(child, indent) |
153 | | - if element.tail: |
154 | | - rv.append("|%s\"%s\"" %(' '*(indent-2), element.tail)) |
155 | | - serializeElement(element, 0) |
156 | | - |
157 | | - if finalText is not None: |
158 | | - rv.append("|%s\"%s\""%(' '*2, finalText)) |
159 | | - |
160 | | - return "\n".join(rv) |
161 | | - |
162 | | -def tostring(element): |
163 | | - """Serialize an element and its child nodes to a string""" |
164 | | - rv = [] |
165 | | - finalText = None |
166 | | - def serializeElement(element): |
167 | | - if element.tag is DocumentType: |
168 | | - rv.append("<!DOCTYPE %s>"%(element.text,)) |
169 | | - elif element.tag is Document: |
170 | | - if element.text: |
171 | | - rv.append(element.text) |
172 | | - if element.tail: |
173 | | - finalText = element.tail |
174 | | - |
175 | | - for child in element.getchildren(): |
176 | | - serializeElement(child) |
177 | | - |
178 | | - elif element.tag is ElementTree.Comment: |
179 | | - rv.append("<!--%s-->"%(element.text,)) |
180 | | - else: |
181 | | - #This is assumed to be an ordinary element |
182 | | - if not element.attrib: |
183 | | - rv.append("<%s>"%(element.tag,)) |
184 | | - else: |
185 | | - attr = " ".join(["%s=\"%s\""%(name, value) |
186 | | - for name, value in element.attrib.iteritems()]) |
187 | | - rv.append("<%s %s>"%(element.tag, attr)) |
188 | | - if element.text: |
189 | | - rv.append(element.text) |
190 | | - |
191 | | - for child in element.getchildren(): |
192 | | - serializeElement(child) |
193 | | - |
194 | | - rv.append("</%s>"%(element.tag,)) |
195 | | - |
196 | | - if element.tail: |
197 | | - rv.append(element.tail) |
198 | | - |
199 | | - serializeElement(element) |
200 | | - |
201 | | - if finalText is not None: |
202 | | - rv.append("%s\""%(' '*2, finalText)) |
203 | | - |
204 | | - return "".join(rv) |
205 | | - |
206 | | -class TreeBuilderFull(_base.TreeBuilder): |
207 | | - documentClass = Document |
208 | | - doctypeClass = DocumentType |
209 | | - elementClass = Element |
210 | | - commentClass = Comment |
211 | | - |
212 | | - def testSerializer(self, element): |
213 | | - return testSerializer(element) |
214 | | - |
215 | | - def getDocument(self): |
216 | | - return self.document._element |
217 | | - |
218 | | -class TreeBuilder(TreeBuilderFull): |
| 3 | +class TreeBuilder(etreefull.TreeBuilder): |
219 | 4 | def getDocument(self): |
220 | 5 | return self.document._element.find("html") |
0 commit comments