author | Andrey Skvortsov <andrej.skvortzov@gmail.com> |
Thu, 27 Jul 2017 20:34:38 +0000 | |
branch | 1.1 Korean release |
changeset 2563 | 18b6352e096a |
parent 1330 | 96b242e4c59d |
child 1385 | 816705d1e512 |
permissions | -rw-r--r-- |
814 | 1 |
#!/usr/bin/env python |
2 |
# -*- coding: utf-8 -*- |
|
3 |
||
4 |
#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor |
|
5 |
#based on the plcopen standard. |
|
6 |
# |
|
7 |
#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD |
|
8 |
# |
|
9 |
#See COPYING file for copyrights details. |
|
10 |
# |
|
11 |
#This library is free software; you can redistribute it and/or |
|
12 |
#modify it under the terms of the GNU General Public |
|
13 |
#License as published by the Free Software Foundation; either |
|
14 |
#version 2.1 of the License, or (at your option) any later version. |
|
15 |
# |
|
16 |
#This library is distributed in the hope that it will be useful, |
|
17 |
#but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
18 |
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
19 |
#General Public License for more details. |
|
20 |
# |
|
21 |
#You should have received a copy of the GNU General Public |
|
22 |
#License along with this library; if not, write to the Free Software |
|
23 |
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
24 |
||
25 |
import os, sys |
|
26 |
import re |
|
27 |
import datetime |
|
28 |
from types import * |
|
29 |
from xml.dom import minidom |
|
30 |
from xml.sax.saxutils import escape, unescape, quoteattr |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
31 |
from lxml import etree |
814 | 32 |
from new import classobj |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
33 |
from collections import OrderedDict |
814 | 34 |
|
35 |
def CreateNode(name): |
|
36 |
node = minidom.Node() |
|
37 |
node.nodeName = name |
|
38 |
node._attrs = {} |
|
39 |
node.childNodes = [] |
|
40 |
return node |
|
41 |
||
42 |
def NodeRenameAttr(node, old_name, new_name): |
|
43 |
node._attrs[new_name] = node._attrs.pop(old_name) |
|
44 |
||
45 |
def NodeSetAttr(node, name, value): |
|
46 |
attr = minidom.Attr(name) |
|
47 |
text = minidom.Text() |
|
48 |
text.data = value |
|
49 |
attr.childNodes[0] = text |
|
50 |
node._attrs[name] = attr |
|
51 |
||
52 |
""" |
|
53 |
Regular expression models for checking all kind of string values defined in XML |
|
54 |
standard |
|
55 |
""" |
|
56 |
Name_model = re.compile('([a-zA-Z_\:][\w\.\-\:]*)$') |
|
57 |
Names_model = re.compile('([a-zA-Z_\:][\w\.\-\:]*(?: [a-zA-Z_\:][\w\.\-\:]*)*)$') |
|
58 |
NMToken_model = re.compile('([\w\.\-\:]*)$') |
|
59 |
NMTokens_model = re.compile('([\w\.\-\:]*(?: [\w\.\-\:]*)*)$') |
|
60 |
QName_model = re.compile('((?:[a-zA-Z_][\w]*:)?[a-zA-Z_][\w]*)$') |
|
61 |
QNames_model = re.compile('((?:[a-zA-Z_][\w]*:)?[a-zA-Z_][\w]*(?: (?:[a-zA-Z_][\w]*:)?[a-zA-Z_][\w]*)*)$') |
|
62 |
NCName_model = re.compile('([a-zA-Z_][\w]*)$') |
|
63 |
URI_model = re.compile('((?:http://|/)?(?:[\w.-]*/?)*)$') |
|
64 |
LANGUAGE_model = re.compile('([a-zA-Z]{1,8}(?:-[a-zA-Z0-9]{1,8})*)$') |
|
65 |
||
66 |
ONLY_ANNOTATION = re.compile("((?:annotation )?)") |
|
67 |
||
68 |
""" |
|
69 |
Regular expression models for extracting dates and times from a string |
|
70 |
""" |
|
71 |
time_model = re.compile('([0-9]{2}):([0-9]{2}):([0-9]{2}(?:\.[0-9]*)?)(?:Z)?$') |
|
72 |
date_model = re.compile('([0-9]{4})-([0-9]{2})-([0-9]{2})((?:[\-\+][0-9]{2}:[0-9]{2})|Z)?$') |
|
73 |
datetime_model = re.compile('([0-9]{4})-([0-9]{2})-([0-9]{2})[ T]([0-9]{2}):([0-9]{2}):([0-9]{2}(?:\.[0-9]*)?)((?:[\-\+][0-9]{2}:[0-9]{2})|Z)?$') |
|
74 |
||
75 |
class xml_timezone(datetime.tzinfo): |
|
76 |
||
77 |
def SetOffset(self, offset): |
|
78 |
if offset == "Z": |
|
79 |
self.__offset = timedelta(minutes = 0) |
|
80 |
self.__name = "UTC" |
|
81 |
else: |
|
82 |
sign = {"-" : -1, "+" : 1}[offset[0]] |
|
83 |
hours, minutes = [int(val) for val in offset[1:].split(":")] |
|
84 |
self.__offset = timedelta(minutes=sign * (hours * 60 + minutes)) |
|
85 |
self.__name = "" |
|
86 |
||
87 |
def utcoffset(self, dt): |
|
88 |
return self.__offset |
|
89 |
||
90 |
def tzname(self, dt): |
|
91 |
return self.__name |
|
92 |
||
93 |
def dst(self, dt): |
|
94 |
return ZERO |
|
95 |
||
96 |
[SYNTAXELEMENT, SYNTAXATTRIBUTE, SIMPLETYPE, COMPLEXTYPE, COMPILEDCOMPLEXTYPE, |
|
97 |
ATTRIBUTESGROUP, ELEMENTSGROUP, ATTRIBUTE, ELEMENT, CHOICE, ANY, TAG, CONSTRAINT, |
|
98 |
] = range(13) |
|
99 |
||
100 |
def NotSupportedYet(type): |
|
101 |
""" |
|
102 |
Function that generates a function that point out to user that datatype |
|
103 |
used is not supported by xmlclass yet |
|
104 |
@param type: data type |
|
105 |
@return: function generated |
|
106 |
""" |
|
107 |
def GetUnknownValue(attr): |
|
108 |
raise ValueError("\"%s\" type isn't supported by \"xmlclass\" yet!" % \ |
|
109 |
type) |
|
110 |
return GetUnknownValue |
|
111 |
||
112 |
""" |
|
113 |
This function calculates the number of whitespace for indentation |
|
114 |
""" |
|
115 |
def getIndent(indent, balise): |
|
116 |
first = indent * 2 |
|
117 |
second = first + len(balise) + 1 |
|
118 |
return u'\t'.expandtabs(first), u'\t'.expandtabs(second) |
|
119 |
||
120 |
||
121 |
def GetAttributeValue(attr, extract=True): |
|
122 |
""" |
|
123 |
Function that extracts data from a tree node |
|
124 |
@param attr: tree node containing data to extract |
|
125 |
@param extract: attr is a tree node or not |
|
126 |
@return: data extracted as string |
|
127 |
""" |
|
128 |
if not extract: |
|
129 |
return attr |
|
130 |
if len(attr.childNodes) == 1: |
|
131 |
return unicode(unescape(attr.childNodes[0].data)) |
|
132 |
else: |
|
133 |
# content is a CDATA |
|
134 |
text = u'' |
|
135 |
for node in attr.childNodes: |
|
136 |
if not (node.nodeName == "#text" and node.data.strip() == u''): |
|
137 |
text += unicode(unescape(node.data)) |
|
138 |
return text |
|
139 |
||
140 |
||
141 |
def GetNormalizedString(attr, extract=True): |
|
142 |
""" |
|
143 |
Function that normalizes a string according to XML 1.0. Replace |
|
144 |
tabulations, line feed and carriage return by white space |
|
145 |
@param attr: tree node containing data to extract or data to normalize |
|
146 |
@param extract: attr is a tree node or not |
|
147 |
@return: data normalized as string |
|
148 |
""" |
|
149 |
if extract: |
|
150 |
value = GetAttributeValue(attr) |
|
151 |
else: |
|
152 |
value = attr |
|
153 |
return value.replace("\t", " ").replace("\r", " ").replace("\n", " ") |
|
154 |
||
155 |
||
156 |
def GetToken(attr, extract=True): |
|
157 |
""" |
|
158 |
Function that tokenizes a string according to XML 1.0. Remove any leading |
|
159 |
and trailing white space and replace internal sequence of two or more |
|
160 |
spaces by only one white space |
|
161 |
@param attr: tree node containing data to extract or data to tokenize |
|
162 |
@param extract: attr is a tree node or not |
|
163 |
@return: data tokenized as string |
|
164 |
""" |
|
165 |
return " ".join([part for part in |
|
166 |
GetNormalizedString(attr, extract).split(" ") |
|
167 |
if part]) |
|
168 |
||
169 |
||
170 |
def GetHexInteger(attr, extract=True): |
|
171 |
""" |
|
172 |
Function that extracts an hexadecimal integer from a tree node or a string |
|
173 |
@param attr: tree node containing data to extract or data as a string |
|
174 |
@param extract: attr is a tree node or not |
|
175 |
@return: data as an integer |
|
176 |
""" |
|
177 |
if extract: |
|
178 |
value = GetAttributeValue(attr) |
|
179 |
else: |
|
180 |
value = attr |
|
181 |
if len(value) % 2 != 0: |
|
182 |
raise ValueError("\"%s\" isn't a valid hexadecimal integer!" % value) |
|
183 |
try: |
|
184 |
return int(value, 16) |
|
185 |
except: |
|
186 |
raise ValueError("\"%s\" isn't a valid hexadecimal integer!" % value) |
|
187 |
||
188 |
||
189 |
def GenerateIntegerExtraction(minInclusive=None, maxInclusive=None, |
|
190 |
minExclusive=None, maxExclusive=None): |
|
191 |
""" |
|
192 |
Function that generates an extraction function for integer defining min and |
|
193 |
max of integer value |
|
194 |
@param minInclusive: inclusive minimum |
|
195 |
@param maxInclusive: inclusive maximum |
|
196 |
@param minExclusive: exclusive minimum |
|
197 |
@param maxExclusive: exclusive maximum |
|
198 |
@return: function generated |
|
199 |
""" |
|
200 |
def GetInteger(attr, extract=True): |
|
201 |
""" |
|
202 |
Function that extracts an integer from a tree node or a string |
|
203 |
@param attr: tree node containing data to extract or data as a string |
|
204 |
@param extract: attr is a tree node or not |
|
205 |
@return: data as an integer |
|
206 |
""" |
|
207 |
||
208 |
if extract: |
|
209 |
value = GetAttributeValue(attr) |
|
210 |
else: |
|
211 |
value = attr |
|
212 |
try: |
|
213 |
# TODO: permit to write value like 1E2 |
|
214 |
value = int(value) |
|
215 |
except: |
|
216 |
raise ValueError("\"%s\" isn't a valid integer!" % value) |
|
217 |
if minInclusive is not None and value < minInclusive: |
|
218 |
raise ValueError("\"%d\" isn't greater or equal to %d!" % \ |
|
219 |
(value, minInclusive)) |
|
220 |
if maxInclusive is not None and value > maxInclusive: |
|
221 |
raise ValueError("\"%d\" isn't lesser or equal to %d!" % \ |
|
222 |
(value, maxInclusive)) |
|
223 |
if minExclusive is not None and value <= minExclusive: |
|
224 |
raise ValueError("\"%d\" isn't greater than %d!" % \ |
|
225 |
(value, minExclusive)) |
|
226 |
if maxExclusive is not None and value >= maxExclusive: |
|
227 |
raise ValueError("\"%d\" isn't lesser than %d!" % \ |
|
228 |
(value, maxExclusive)) |
|
229 |
return value |
|
230 |
return GetInteger |
|
231 |
||
232 |
||
233 |
def GenerateFloatExtraction(type, extra_values=[]): |
|
234 |
""" |
|
235 |
Function that generates an extraction function for float |
|
236 |
@param type: name of the type of float |
|
237 |
@return: function generated |
|
238 |
""" |
|
239 |
def GetFloat(attr, extract = True): |
|
240 |
""" |
|
241 |
Function that extracts a float from a tree node or a string |
|
242 |
@param attr: tree node containing data to extract or data as a string |
|
243 |
@param extract: attr is a tree node or not |
|
244 |
@return: data as a float |
|
245 |
""" |
|
246 |
if extract: |
|
247 |
value = GetAttributeValue(attr) |
|
248 |
else: |
|
249 |
value = attr |
|
250 |
if value in extra_values: |
|
251 |
return value |
|
252 |
try: |
|
253 |
return float(value) |
|
254 |
except: |
|
255 |
raise ValueError("\"%s\" isn't a valid %s!" % (value, type)) |
|
256 |
return GetFloat |
|
257 |
||
258 |
||
259 |
def GetBoolean(attr, extract=True): |
|
260 |
""" |
|
261 |
Function that extracts a boolean from a tree node or a string |
|
262 |
@param attr: tree node containing data to extract or data as a string |
|
263 |
@param extract: attr is a tree node or not |
|
264 |
@return: data as a boolean |
|
265 |
""" |
|
266 |
if extract: |
|
267 |
value = GetAttributeValue(attr) |
|
268 |
else: |
|
269 |
value = attr |
|
270 |
if value == "true" or value == "1": |
|
271 |
return True |
|
272 |
elif value == "false" or value == "0": |
|
273 |
return False |
|
274 |
else: |
|
275 |
raise ValueError("\"%s\" isn't a valid boolean!" % value) |
|
276 |
||
277 |
||
278 |
def GetTime(attr, extract=True): |
|
279 |
""" |
|
280 |
Function that extracts a time from a tree node or a string |
|
281 |
@param attr: tree node containing data to extract or data as a string |
|
282 |
@param extract: attr is a tree node or not |
|
283 |
@return: data as a time |
|
284 |
""" |
|
285 |
if extract: |
|
286 |
value = GetAttributeValue(attr) |
|
287 |
else: |
|
288 |
value = attr |
|
289 |
result = time_model.match(value) |
|
290 |
if result: |
|
291 |
values = result.groups() |
|
292 |
time_values = [int(v) for v in values[:2]] |
|
293 |
seconds = float(values[2]) |
|
294 |
time_values.extend([int(seconds), int((seconds % 1) * 1000000)]) |
|
295 |
return datetime.time(*time_values) |
|
296 |
else: |
|
297 |
raise ValueError("\"%s\" isn't a valid time!" % value) |
|
298 |
||
299 |
||
300 |
def GetDate(attr, extract=True): |
|
301 |
""" |
|
302 |
Function that extracts a date from a tree node or a string |
|
303 |
@param attr: tree node containing data to extract or data as a string |
|
304 |
@param extract: attr is a tree node or not |
|
305 |
@return: data as a date |
|
306 |
""" |
|
307 |
if extract: |
|
308 |
value = GetAttributeValue(attr) |
|
309 |
else: |
|
310 |
value = attr |
|
311 |
result = date_model.match(value) |
|
312 |
if result: |
|
313 |
values = result.groups() |
|
314 |
date_values = [int(v) for v in values[:3]] |
|
315 |
if values[3] is not None: |
|
316 |
tz = xml_timezone() |
|
317 |
tz.SetOffset(values[3]) |
|
318 |
date_values.append(tz) |
|
319 |
return datetime.date(*date_values) |
|
320 |
else: |
|
321 |
raise ValueError("\"%s\" isn't a valid date!" % value) |
|
322 |
||
323 |
||
324 |
def GetDateTime(attr, extract=True): |
|
325 |
""" |
|
326 |
Function that extracts date and time from a tree node or a string |
|
327 |
@param attr: tree node containing data to extract or data as a string |
|
328 |
@param extract: attr is a tree node or not |
|
329 |
@return: data as date and time |
|
330 |
""" |
|
331 |
if extract: |
|
332 |
value = GetAttributeValue(attr) |
|
333 |
else: |
|
334 |
value = attr |
|
335 |
result = datetime_model.match(value) |
|
336 |
if result: |
|
337 |
values = result.groups() |
|
338 |
datetime_values = [int(v) for v in values[:5]] |
|
339 |
seconds = float(values[5]) |
|
340 |
datetime_values.extend([int(seconds), int((seconds % 1) * 1000000)]) |
|
341 |
if values[6] is not None: |
|
342 |
tz = xml_timezone() |
|
343 |
tz.SetOffset(values[6]) |
|
344 |
datetime_values.append(tz) |
|
345 |
return datetime.datetime(*datetime_values) |
|
346 |
else: |
|
347 |
raise ValueError("\"%s\" isn't a valid datetime!" % value) |
|
348 |
||
349 |
||
350 |
def GenerateModelNameExtraction(type, model): |
|
351 |
""" |
|
352 |
Function that generates an extraction function for string matching a model |
|
353 |
@param type: name of the data type |
|
354 |
@param model: model that data must match |
|
355 |
@return: function generated |
|
356 |
""" |
|
357 |
def GetModelName(attr, extract=True): |
|
358 |
""" |
|
359 |
Function that extracts a string from a tree node or not and check that |
|
360 |
string extracted or given match the model |
|
361 |
@param attr: tree node containing data to extract or data as a string |
|
362 |
@param extract: attr is a tree node or not |
|
363 |
@return: data as a string if matching |
|
364 |
""" |
|
365 |
if extract: |
|
366 |
value = GetAttributeValue(attr) |
|
367 |
else: |
|
368 |
value = attr |
|
369 |
result = model.match(value) |
|
370 |
if not result: |
|
371 |
raise ValueError("\"%s\" isn't a valid %s!" % (value, type)) |
|
372 |
return value |
|
373 |
return GetModelName |
|
374 |
||
375 |
||
376 |
def GenerateLimitExtraction(min=None, max=None, unbounded=True): |
|
377 |
""" |
|
378 |
Function that generates an extraction function for integer defining min and |
|
379 |
max of integer value |
|
380 |
@param min: minimum limit value |
|
381 |
@param max: maximum limit value |
|
382 |
@param unbounded: value can be "unbounded" or not |
|
383 |
@return: function generated |
|
384 |
""" |
|
385 |
def GetLimit(attr, extract=True): |
|
386 |
""" |
|
387 |
Function that extracts a string from a tree node or not and check that |
|
388 |
string extracted or given is in a list of values |
|
389 |
@param attr: tree node containing data to extract or data as a string |
|
390 |
@param extract: attr is a tree node or not |
|
391 |
@return: data as a string |
|
392 |
""" |
|
393 |
if extract: |
|
394 |
value = GetAttributeValue(attr) |
|
395 |
else: |
|
396 |
value = attr |
|
397 |
if value == "unbounded": |
|
398 |
if unbounded: |
|
399 |
return value |
|
400 |
else: |
|
401 |
raise ValueError("Member limit can't be defined to \"unbounded\"!") |
|
402 |
try: |
|
403 |
limit = int(value) |
|
404 |
except: |
|
405 |
raise ValueError("\"%s\" isn't a valid value for this member limit!" % value) |
|
406 |
if limit < 0: |
|
407 |
raise ValueError("Member limit can't be negative!") |
|
408 |
elif min is not None and limit < min: |
|
409 |
raise ValueError("Member limit can't be lower than \"%d\"!" % min) |
|
410 |
elif max is not None and limit > max: |
|
411 |
raise ValueError("Member limit can't be upper than \"%d\"!" % max) |
|
412 |
return limit |
|
413 |
return GetLimit |
|
414 |
||
415 |
||
416 |
def GenerateEnumeratedExtraction(type, list): |
|
417 |
""" |
|
418 |
Function that generates an extraction function for enumerated values |
|
419 |
@param type: name of the data type |
|
420 |
@param list: list of possible values |
|
421 |
@return: function generated |
|
422 |
""" |
|
423 |
def GetEnumerated(attr, extract=True): |
|
424 |
""" |
|
425 |
Function that extracts a string from a tree node or not and check that |
|
426 |
string extracted or given is in a list of values |
|
427 |
@param attr: tree node containing data to extract or data as a string |
|
428 |
@param extract: attr is a tree node or not |
|
429 |
@return: data as a string |
|
430 |
""" |
|
431 |
if extract: |
|
432 |
value = GetAttributeValue(attr) |
|
433 |
else: |
|
434 |
value = attr |
|
435 |
if value in list: |
|
436 |
return value |
|
437 |
else: |
|
438 |
raise ValueError("\"%s\" isn't a valid value for %s!" % \ |
|
439 |
(value, type)) |
|
440 |
return GetEnumerated |
|
441 |
||
442 |
||
443 |
def GetNamespaces(attr, extract=True): |
|
444 |
""" |
|
445 |
Function that extracts a list of namespaces from a tree node or a string |
|
446 |
@param attr: tree node containing data to extract or data as a string |
|
447 |
@param extract: attr is a tree node or not |
|
448 |
@return: list of namespaces |
|
449 |
""" |
|
450 |
if extract: |
|
451 |
value = GetAttributeValue(attr) |
|
452 |
else: |
|
453 |
value = attr |
|
454 |
if value == "": |
|
455 |
return [] |
|
456 |
elif value == "##any" or value == "##other": |
|
457 |
namespaces = [value] |
|
458 |
else: |
|
459 |
namespaces = [] |
|
460 |
for item in value.split(" "): |
|
461 |
if item == "##targetNamespace" or item == "##local": |
|
462 |
namespaces.append(item) |
|
463 |
else: |
|
464 |
result = URI_model.match(item) |
|
465 |
if result is not None: |
|
466 |
namespaces.append(item) |
|
467 |
else: |
|
468 |
raise ValueError("\"%s\" isn't a valid value for namespace!" % value) |
|
469 |
return namespaces |
|
470 |
||
471 |
||
472 |
def GenerateGetList(type, list): |
|
473 |
""" |
|
474 |
Function that generates an extraction function for a list of values |
|
475 |
@param type: name of the data type |
|
476 |
@param list: list of possible values |
|
477 |
@return: function generated |
|
478 |
""" |
|
479 |
def GetLists(attr, extract=True): |
|
480 |
""" |
|
481 |
Function that extracts a list of values from a tree node or a string |
|
482 |
@param attr: tree node containing data to extract or data as a string |
|
483 |
@param extract: attr is a tree node or not |
|
484 |
@return: list of values |
|
485 |
""" |
|
486 |
if extract: |
|
487 |
value = GetAttributeValue(attr) |
|
488 |
else: |
|
489 |
value = attr |
|
490 |
if value == "": |
|
491 |
return [] |
|
492 |
elif value == "#all": |
|
493 |
return [value] |
|
494 |
else: |
|
495 |
values = [] |
|
496 |
for item in value.split(" "): |
|
497 |
if item in list: |
|
498 |
values.append(item) |
|
499 |
else: |
|
500 |
raise ValueError("\"%s\" isn't a valid value for %s!" % \ |
|
501 |
(value, type)) |
|
502 |
return values |
|
503 |
return GetLists |
|
504 |
||
505 |
||
506 |
def GenerateModelNameListExtraction(type, model): |
|
507 |
""" |
|
508 |
Function that generates an extraction function for list of string matching |
|
509 |
a model |
|
510 |
@param type: name of the data type |
|
511 |
@param model: model that list elements must match |
|
512 |
@return: function generated |
|
513 |
""" |
|
514 |
def GetModelNameList(attr, extract=True): |
|
515 |
""" |
|
516 |
Function that extracts a list of string from a tree node or not and |
|
517 |
check that all extracted items match the model |
|
518 |
@param attr: tree node containing data to extract or data as a string |
|
519 |
@param extract: attr is a tree node or not |
|
520 |
@return: data as a list of string if matching |
|
521 |
""" |
|
522 |
if extract: |
|
523 |
value = GetAttributeValue(attr) |
|
524 |
else: |
|
525 |
value = attr |
|
526 |
values = [] |
|
527 |
for item in value.split(" "): |
|
528 |
result = model.match(item) |
|
529 |
if result is not None: |
|
530 |
values.append(item) |
|
531 |
else: |
|
532 |
raise ValueError("\"%s\" isn't a valid value for %s!" % \ |
|
533 |
(value, type)) |
|
534 |
return values |
|
535 |
return GetModelNameList |
|
536 |
||
537 |
def GenerateAnyInfos(infos): |
|
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
538 |
|
1294
f02ba5b83811
Fixed datatype and configuration editing in xmlclass refactoring
Laurent Bessard
parents:
1293
diff
changeset
|
539 |
def GetTextElement(tree): |
f02ba5b83811
Fixed datatype and configuration editing in xmlclass refactoring
Laurent Bessard
parents:
1293
diff
changeset
|
540 |
if infos["namespace"][0] == "##any": |
f02ba5b83811
Fixed datatype and configuration editing in xmlclass refactoring
Laurent Bessard
parents:
1293
diff
changeset
|
541 |
return tree.xpath("p")[0] |
f02ba5b83811
Fixed datatype and configuration editing in xmlclass refactoring
Laurent Bessard
parents:
1293
diff
changeset
|
542 |
return tree.xpath("ns:p", namespaces={"ns": infos["namespace"][0]})[0] |
f02ba5b83811
Fixed datatype and configuration editing in xmlclass refactoring
Laurent Bessard
parents:
1293
diff
changeset
|
543 |
|
814 | 544 |
def ExtractAny(tree): |
1294
f02ba5b83811
Fixed datatype and configuration editing in xmlclass refactoring
Laurent Bessard
parents:
1293
diff
changeset
|
545 |
return GetTextElement(tree).text |
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
546 |
|
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
547 |
def GenerateAny(tree, value): |
1294
f02ba5b83811
Fixed datatype and configuration editing in xmlclass refactoring
Laurent Bessard
parents:
1293
diff
changeset
|
548 |
GetTextElement(tree).text = etree.CDATA(value) |
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
549 |
|
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
550 |
def InitialAny(): |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
551 |
if infos["namespace"][0] == "##any": |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
552 |
element_name = "p" |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
553 |
else: |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
554 |
element_name = "{%s}p" % infos["namespace"][0] |
1293
40117d02601b
Fixed diagram editing in xmlclass refactoring
Laurent Bessard
parents:
1291
diff
changeset
|
555 |
p = etree.Element(element_name) |
40117d02601b
Fixed diagram editing in xmlclass refactoring
Laurent Bessard
parents:
1291
diff
changeset
|
556 |
p.text = etree.CDATA("") |
40117d02601b
Fixed diagram editing in xmlclass refactoring
Laurent Bessard
parents:
1291
diff
changeset
|
557 |
return p |
814 | 558 |
|
559 |
return { |
|
560 |
"type": COMPLEXTYPE, |
|
561 |
"extract": ExtractAny, |
|
562 |
"generate": GenerateAny, |
|
1293
40117d02601b
Fixed diagram editing in xmlclass refactoring
Laurent Bessard
parents:
1291
diff
changeset
|
563 |
"initial": InitialAny, |
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
564 |
"check": lambda x: isinstance(x, (StringType, UnicodeType, etree.ElementBase)) |
814 | 565 |
} |
566 |
||
567 |
def GenerateTagInfos(infos): |
|
568 |
def ExtractTag(tree): |
|
569 |
if len(tree._attrs) > 0: |
|
570 |
raise ValueError("\"%s\" musn't have attributes!" % infos["name"]) |
|
571 |
if len(tree.childNodes) > 0: |
|
572 |
raise ValueError("\"%s\" musn't have children!" % infos["name"]) |
|
573 |
if infos["minOccurs"] == 0: |
|
574 |
return True |
|
575 |
else: |
|
576 |
return None |
|
577 |
||
578 |
def GenerateTag(value, name=None, indent=0): |
|
579 |
if name is not None and not (infos["minOccurs"] == 0 and value is None): |
|
580 |
ind1, ind2 = getIndent(indent, name) |
|
581 |
return ind1 + "<%s/>\n" % name |
|
582 |
else: |
|
583 |
return "" |
|
584 |
||
585 |
return { |
|
586 |
"type": TAG, |
|
587 |
"extract": ExtractTag, |
|
588 |
"generate": GenerateTag, |
|
589 |
"initial": lambda: None, |
|
590 |
"check": lambda x: x == None or infos["minOccurs"] == 0 and value == True |
|
591 |
} |
|
592 |
||
593 |
def FindTypeInfos(factory, infos): |
|
594 |
if isinstance(infos, (UnicodeType, StringType)): |
|
595 |
namespace, name = DecomposeQualifiedName(infos) |
|
596 |
return factory.GetQualifiedNameInfos(name, namespace) |
|
597 |
return infos |
|
598 |
||
599 |
def GetElementInitialValue(factory, infos): |
|
600 |
infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"]) |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
601 |
if infos["minOccurs"] == 1: |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
602 |
element_name = factory.etreeNamespaceFormat % infos["name"] |
1293
40117d02601b
Fixed diagram editing in xmlclass refactoring
Laurent Bessard
parents:
1291
diff
changeset
|
603 |
if infos["elmt_type"]["type"] == SIMPLETYPE: |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
604 |
def initial_value(): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
605 |
value = etree.Element(element_name) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
606 |
value.text = (infos["elmt_type"]["generate"](infos["elmt_type"]["initial"]())) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
607 |
return value |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
608 |
else: |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
609 |
def initial_value(): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
610 |
value = infos["elmt_type"]["initial"]() |
1293
40117d02601b
Fixed diagram editing in xmlclass refactoring
Laurent Bessard
parents:
1291
diff
changeset
|
611 |
if infos["type"] != ANY: |
40117d02601b
Fixed diagram editing in xmlclass refactoring
Laurent Bessard
parents:
1291
diff
changeset
|
612 |
DefaultElementClass.__setattr__(value, "tag", element_name) |
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
613 |
value._init_() |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
614 |
return value |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
615 |
return [initial_value() for i in xrange(infos["minOccurs"])] |
814 | 616 |
else: |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
617 |
return [] |
814 | 618 |
|
619 |
def GetContentInfos(name, choices): |
|
620 |
for choice_infos in choices: |
|
621 |
if choices_infos["type"] == "sequence": |
|
622 |
for element_infos in choices_infos["elements"]: |
|
623 |
if element_infos["type"] == CHOICE: |
|
624 |
if GetContentInfos(name, element_infos["choices"]): |
|
625 |
return choices_infos |
|
626 |
elif element_infos["name"] == name: |
|
627 |
return choices_infos |
|
628 |
elif choice_infos["name"] == name: |
|
629 |
return choices_infos |
|
630 |
return None |
|
631 |
||
632 |
def ComputeContentChoices(factory, name, infos): |
|
633 |
choices = [] |
|
634 |
for choice in infos["choices"]: |
|
635 |
if choice["type"] == "sequence": |
|
636 |
choice["name"] = "sequence" |
|
637 |
for sequence_element in choice["elements"]: |
|
638 |
if sequence_element["type"] != CHOICE: |
|
639 |
element_infos = factory.ExtractTypeInfos(sequence_element["name"], name, sequence_element["elmt_type"]) |
|
640 |
if element_infos is not None: |
|
641 |
sequence_element["elmt_type"] = element_infos |
|
642 |
elif choice["elmt_type"] == "tag": |
|
643 |
choice["elmt_type"] = GenerateTagInfos(choice) |
|
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
644 |
factory.AddToLookupClass(choice["name"], name, DefaultElementClass) |
814 | 645 |
else: |
646 |
choice_infos = factory.ExtractTypeInfos(choice["name"], name, choice["elmt_type"]) |
|
647 |
if choice_infos is not None: |
|
648 |
choice["elmt_type"] = choice_infos |
|
649 |
choices.append((choice["name"], choice)) |
|
650 |
return choices |
|
651 |
||
652 |
def GenerateContentInfos(factory, name, choices): |
|
653 |
choices_dict = {} |
|
654 |
for choice_name, infos in choices: |
|
655 |
if choice_name == "sequence": |
|
656 |
for element in infos["elements"]: |
|
657 |
if element["type"] == CHOICE: |
|
658 |
element["elmt_type"] = GenerateContentInfos(factory, name, ComputeContentChoices(factory, name, element)) |
|
659 |
elif choices_dict.has_key(element["name"]): |
|
660 |
raise ValueError("'%s' element defined two times in choice" % choice_name) |
|
661 |
else: |
|
662 |
choices_dict[element["name"]] = infos |
|
663 |
else: |
|
664 |
if choices_dict.has_key(choice_name): |
|
665 |
raise ValueError("'%s' element defined two times in choice" % choice_name) |
|
666 |
choices_dict[choice_name] = infos |
|
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
667 |
prefix = ("%s:" % factory.TargetNamespace |
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
668 |
if factory.TargetNamespace is not None else "") |
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
669 |
choices_xpath = "|".join(map(lambda x: prefix + x, choices_dict.keys())) |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
670 |
|
814 | 671 |
def GetContentInitial(): |
672 |
content_name, infos = choices[0] |
|
673 |
if content_name == "sequence": |
|
674 |
content_value = [] |
|
675 |
for i in xrange(infos["minOccurs"]): |
|
676 |
for element_infos in infos["elements"]: |
|
1305
714f1381a09a
Fixed xmlclass and plcopen using precompile xpath where possible
Laurent Bessard
parents:
1304
diff
changeset
|
677 |
content_value.extend(GetElementInitialValue(factory, element_infos)) |
814 | 678 |
else: |
679 |
content_value = GetElementInitialValue(factory, infos) |
|
1305
714f1381a09a
Fixed xmlclass and plcopen using precompile xpath where possible
Laurent Bessard
parents:
1304
diff
changeset
|
680 |
return content_value |
814 | 681 |
|
682 |
return { |
|
683 |
"type": COMPLEXTYPE, |
|
1305
714f1381a09a
Fixed xmlclass and plcopen using precompile xpath where possible
Laurent Bessard
parents:
1304
diff
changeset
|
684 |
"choices_xpath": etree.XPath(choices_xpath, namespaces=factory.NSMAP), |
814 | 685 |
"initial": GetContentInitial, |
686 |
} |
|
687 |
||
688 |
#------------------------------------------------------------------------------- |
|
689 |
# Structure extraction functions |
|
690 |
#------------------------------------------------------------------------------- |
|
691 |
||
692 |
||
693 |
def DecomposeQualifiedName(name): |
|
694 |
result = QName_model.match(name) |
|
695 |
if not result: |
|
696 |
raise ValueError("\"%s\" isn't a valid QName value!" % name) |
|
697 |
parts = result.groups()[0].split(':') |
|
698 |
if len(parts) == 1: |
|
699 |
return None, parts[0] |
|
700 |
return parts |
|
701 |
||
702 |
def GenerateElement(element_name, attributes, elements_model, |
|
703 |
accept_text=False): |
|
704 |
def ExtractElement(factory, node): |
|
705 |
attrs = factory.ExtractNodeAttrs(element_name, node, attributes) |
|
706 |
children_structure = "" |
|
707 |
children_infos = [] |
|
708 |
children = [] |
|
709 |
for child in node.childNodes: |
|
710 |
if child.nodeName not in ["#comment", "#text"]: |
|
711 |
namespace, childname = DecomposeQualifiedName(child.nodeName) |
|
712 |
children_structure += "%s "%childname |
|
713 |
result = elements_model.match(children_structure) |
|
714 |
if not result: |
|
715 |
raise ValueError("Invalid structure for \"%s\" children!. First element invalid." % node.nodeName) |
|
716 |
valid = result.groups()[0] |
|
717 |
if len(valid) < len(children_structure): |
|
718 |
raise ValueError("Invalid structure for \"%s\" children!. Element number %d invalid." % (node.nodeName, len(valid.split(" ")) - 1)) |
|
719 |
for child in node.childNodes: |
|
720 |
if child.nodeName != "#comment" and \ |
|
721 |
(accept_text or child.nodeName != "#text"): |
|
722 |
if child.nodeName == "#text": |
|
723 |
children.append(GetAttributeValue(node)) |
|
724 |
else: |
|
725 |
namespace, childname = DecomposeQualifiedName(child.nodeName) |
|
726 |
infos = factory.GetQualifiedNameInfos(childname, namespace) |
|
727 |
if infos["type"] != SYNTAXELEMENT: |
|
728 |
raise ValueError("\"%s\" can't be a member child!" % name) |
|
729 |
if infos["extract"].has_key(element_name): |
|
730 |
children.append(infos["extract"][element_name](factory, child)) |
|
731 |
else: |
|
732 |
children.append(infos["extract"]["default"](factory, child)) |
|
733 |
return node.nodeName, attrs, children |
|
734 |
return ExtractElement |
|
735 |
||
736 |
||
737 |
""" |
|
738 |
Class that generate class from an XML Tree |
|
739 |
""" |
|
740 |
class ClassFactory: |
|
741 |
||
742 |
def __init__(self, document, filepath=None, debug=False): |
|
743 |
self.Document = document |
|
744 |
if filepath is not None: |
|
745 |
self.BaseFolder, self.FileName = os.path.split(filepath) |
|
746 |
else: |
|
747 |
self.BaseFolder = self.FileName = None |
|
748 |
self.Debug = debug |
|
749 |
||
750 |
# Dictionary for stocking Classes and Types definitions created from |
|
751 |
# the XML tree |
|
752 |
self.XMLClassDefinitions = {} |
|
753 |
||
754 |
self.DefinedNamespaces = {} |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
755 |
self.NSMAP = {} |
814 | 756 |
self.Namespaces = {} |
757 |
self.SchemaNamespace = None |
|
758 |
self.TargetNamespace = None |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
759 |
self.etreeNamespaceFormat = "%s" |
814 | 760 |
|
761 |
self.CurrentCompilations = [] |
|
762 |
||
763 |
# Dictionaries for stocking Classes and Types generated |
|
764 |
self.ComputeAfter = [] |
|
765 |
if self.FileName is not None: |
|
766 |
self.ComputedClasses = {self.FileName: {}} |
|
767 |
else: |
|
768 |
self.ComputedClasses = {} |
|
769 |
self.ComputedClassesInfos = {} |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
770 |
self.ComputedClassesLookUp = {} |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
771 |
self.EquivalentClassesParent = {} |
814 | 772 |
self.AlreadyComputed = {} |
773 |
||
774 |
def GetQualifiedNameInfos(self, name, namespace=None, canbenone=False): |
|
775 |
if namespace is None: |
|
776 |
if self.Namespaces[self.SchemaNamespace].has_key(name): |
|
777 |
return self.Namespaces[self.SchemaNamespace][name] |
|
778 |
for space, elements in self.Namespaces.iteritems(): |
|
779 |
if space != self.SchemaNamespace and elements.has_key(name): |
|
780 |
return elements[name] |
|
781 |
parts = name.split("_", 1) |
|
782 |
if len(parts) > 1: |
|
783 |
group = self.GetQualifiedNameInfos(parts[0], namespace) |
|
784 |
if group is not None and group["type"] == ELEMENTSGROUP: |
|
785 |
elements = [] |
|
786 |
if group.has_key("elements"): |
|
787 |
elements = group["elements"] |
|
788 |
elif group.has_key("choices"): |
|
789 |
elements = group["choices"] |
|
790 |
for element in elements: |
|
791 |
if element["name"] == parts[1]: |
|
792 |
return element |
|
793 |
if not canbenone: |
|
794 |
raise ValueError("Unknown element \"%s\" for any defined namespaces!" % name) |
|
795 |
elif self.Namespaces.has_key(namespace): |
|
796 |
if self.Namespaces[namespace].has_key(name): |
|
797 |
return self.Namespaces[namespace][name] |
|
798 |
parts = name.split("_", 1) |
|
799 |
if len(parts) > 1: |
|
800 |
group = self.GetQualifiedNameInfos(parts[0], namespace) |
|
801 |
if group is not None and group["type"] == ELEMENTSGROUP: |
|
802 |
elements = [] |
|
803 |
if group.has_key("elements"): |
|
804 |
elements = group["elements"] |
|
805 |
elif group.has_key("choices"): |
|
806 |
elements = group["choices"] |
|
807 |
for element in elements: |
|
808 |
if element["name"] == parts[1]: |
|
809 |
return element |
|
810 |
if not canbenone: |
|
811 |
raise ValueError("Unknown element \"%s\" for namespace \"%s\"!" % (name, namespace)) |
|
812 |
elif not canbenone: |
|
813 |
raise ValueError("Unknown namespace \"%s\"!" % namespace) |
|
814 |
return None |
|
815 |
||
816 |
def SplitQualifiedName(self, name, namespace=None, canbenone=False): |
|
817 |
if namespace is None: |
|
818 |
if self.Namespaces[self.SchemaNamespace].has_key(name): |
|
819 |
return name, None |
|
820 |
for space, elements in self.Namespaces.items(): |
|
821 |
if space != self.SchemaNamespace and elements.has_key(name): |
|
822 |
return name, None |
|
823 |
parts = name.split("_", 1) |
|
824 |
if len(parts) > 1: |
|
825 |
group = self.GetQualifiedNameInfos(parts[0], namespace) |
|
826 |
if group is not None and group["type"] == ELEMENTSGROUP: |
|
827 |
elements = [] |
|
828 |
if group.has_key("elements"): |
|
829 |
elements = group["elements"] |
|
830 |
elif group.has_key("choices"): |
|
831 |
elements = group["choices"] |
|
832 |
for element in elements: |
|
833 |
if element["name"] == parts[1]: |
|
834 |
return part[1], part[0] |
|
835 |
if not canbenone: |
|
836 |
raise ValueError("Unknown element \"%s\" for any defined namespaces!" % name) |
|
837 |
elif self.Namespaces.has_key(namespace): |
|
838 |
if self.Namespaces[namespace].has_key(name): |
|
839 |
return name, None |
|
840 |
parts = name.split("_", 1) |
|
841 |
if len(parts) > 1: |
|
842 |
group = self.GetQualifiedNameInfos(parts[0], namespace) |
|
843 |
if group is not None and group["type"] == ELEMENTSGROUP: |
|
844 |
elements = [] |
|
845 |
if group.has_key("elements"): |
|
846 |
elements = group["elements"] |
|
847 |
elif group.has_key("choices"): |
|
848 |
elements = group["choices"] |
|
849 |
for element in elements: |
|
850 |
if element["name"] == parts[1]: |
|
851 |
return parts[1], parts[0] |
|
852 |
if not canbenone: |
|
853 |
raise ValueError("Unknown element \"%s\" for namespace \"%s\"!" % (name, namespace)) |
|
854 |
elif not canbenone: |
|
855 |
raise ValueError("Unknown namespace \"%s\"!" % namespace) |
|
856 |
return None, None |
|
857 |
||
858 |
def ExtractNodeAttrs(self, element_name, node, valid_attrs): |
|
859 |
attrs = {} |
|
860 |
for qualified_name, attr in node._attrs.items(): |
|
861 |
namespace, name = DecomposeQualifiedName(qualified_name) |
|
862 |
if name in valid_attrs: |
|
863 |
infos = self.GetQualifiedNameInfos(name, namespace) |
|
864 |
if infos["type"] != SYNTAXATTRIBUTE: |
|
865 |
raise ValueError("\"%s\" can't be a member attribute!" % name) |
|
866 |
elif name in attrs: |
|
867 |
raise ValueError("\"%s\" attribute has been twice!" % name) |
|
868 |
elif element_name in infos["extract"]: |
|
869 |
attrs[name] = infos["extract"][element_name](attr) |
|
870 |
else: |
|
871 |
attrs[name] = infos["extract"]["default"](attr) |
|
872 |
elif namespace == "xmlns": |
|
873 |
infos = self.GetQualifiedNameInfos("anyURI", self.SchemaNamespace) |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
874 |
value = infos["extract"](attr) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
875 |
self.DefinedNamespaces[value] = name |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
876 |
self.NSMAP[name] = value |
814 | 877 |
else: |
878 |
raise ValueError("Invalid attribute \"%s\" for member \"%s\"!" % (qualified_name, node.nodeName)) |
|
879 |
for attr in valid_attrs: |
|
880 |
if attr not in attrs and \ |
|
881 |
self.Namespaces[self.SchemaNamespace].has_key(attr) and \ |
|
882 |
self.Namespaces[self.SchemaNamespace][attr].has_key("default"): |
|
883 |
if self.Namespaces[self.SchemaNamespace][attr]["default"].has_key(element_name): |
|
884 |
default = self.Namespaces[self.SchemaNamespace][attr]["default"][element_name] |
|
885 |
else: |
|
886 |
default = self.Namespaces[self.SchemaNamespace][attr]["default"]["default"] |
|
887 |
if default is not None: |
|
888 |
attrs[attr] = default |
|
889 |
return attrs |
|
890 |
||
891 |
def ReduceElements(self, elements, schema=False): |
|
892 |
result = [] |
|
893 |
for child_infos in elements: |
|
894 |
if child_infos is not None: |
|
895 |
if child_infos[1].has_key("name") and schema: |
|
896 |
self.CurrentCompilations.append(child_infos[1]["name"]) |
|
897 |
namespace, name = DecomposeQualifiedName(child_infos[0]) |
|
898 |
infos = self.GetQualifiedNameInfos(name, namespace) |
|
899 |
if infos["type"] != SYNTAXELEMENT: |
|
900 |
raise ValueError("\"%s\" can't be a member child!" % name) |
|
901 |
element = infos["reduce"](self, child_infos[1], child_infos[2]) |
|
902 |
if element is not None: |
|
903 |
result.append(element) |
|
904 |
if child_infos[1].has_key("name") and schema: |
|
905 |
self.CurrentCompilations.pop(-1) |
|
906 |
annotations = [] |
|
907 |
children = [] |
|
908 |
for element in result: |
|
909 |
if element["type"] == "annotation": |
|
910 |
annotations.append(element) |
|
911 |
else: |
|
912 |
children.append(element) |
|
913 |
return annotations, children |
|
914 |
||
915 |
def AddComplexType(self, typename, infos): |
|
916 |
if not self.XMLClassDefinitions.has_key(typename): |
|
917 |
self.XMLClassDefinitions[typename] = infos |
|
918 |
else: |
|
919 |
raise ValueError("\"%s\" class already defined. Choose another name!" % typename) |
|
920 |
||
921 |
def ParseSchema(self): |
|
922 |
pass |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
923 |
|
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
924 |
def AddEquivalentClass(self, name, base): |
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
925 |
if name != base: |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
926 |
equivalences = self.EquivalentClassesParent.setdefault(self.etreeNamespaceFormat % base, {}) |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
927 |
equivalences[self.etreeNamespaceFormat % name] = True |
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
928 |
|
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
929 |
def AddDistinctionBetweenParentsInLookupClass( |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
930 |
self, lookup_classes, parent, typeinfos): |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
931 |
parent = (self.etreeNamespaceFormat % parent |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
932 |
if parent is not None else None) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
933 |
parent_class = lookup_classes.get(parent) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
934 |
if parent_class is not None: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
935 |
if isinstance(parent_class, ListType): |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
936 |
if typeinfos not in parent_class: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
937 |
lookup_classes[parent].append(typeinfos) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
938 |
elif parent_class != typeinfos: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
939 |
lookup_classes[parent] = [parent_class, typeinfos] |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
940 |
else: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
941 |
lookup_classes[parent] = typeinfos |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
942 |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
943 |
def AddToLookupClass(self, name, parent, typeinfos): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
944 |
lookup_name = self.etreeNamespaceFormat % name |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
945 |
if isinstance(typeinfos, (StringType, UnicodeType)): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
946 |
self.AddEquivalentClass(name, typeinfos) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
947 |
typeinfos = self.etreeNamespaceFormat % typeinfos |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
948 |
lookup_classes = self.ComputedClassesLookUp.get(lookup_name) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
949 |
if lookup_classes is None: |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
950 |
self.ComputedClassesLookUp[lookup_name] = (typeinfos, parent) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
951 |
elif isinstance(lookup_classes, DictType): |
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
952 |
self.AddDistinctionBetweenParentsInLookupClass( |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
953 |
lookup_classes, parent, typeinfos) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
954 |
else: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
955 |
lookup_classes = { |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
956 |
self.etreeNamespaceFormat % lookup_classes[1] |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
957 |
if lookup_classes[1] is not None else None: lookup_classes[0]} |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
958 |
self.AddDistinctionBetweenParentsInLookupClass( |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
959 |
lookup_classes, parent, typeinfos) |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
960 |
self.ComputedClassesLookUp[lookup_name] = lookup_classes |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
961 |
|
814 | 962 |
def ExtractTypeInfos(self, name, parent, typeinfos): |
963 |
if isinstance(typeinfos, (StringType, UnicodeType)): |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
964 |
namespace, type_name = DecomposeQualifiedName(typeinfos) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
965 |
infos = self.GetQualifiedNameInfos(type_name, namespace) |
1293
40117d02601b
Fixed diagram editing in xmlclass refactoring
Laurent Bessard
parents:
1291
diff
changeset
|
966 |
if name != "base": |
40117d02601b
Fixed diagram editing in xmlclass refactoring
Laurent Bessard
parents:
1291
diff
changeset
|
967 |
if infos["type"] == SIMPLETYPE: |
40117d02601b
Fixed diagram editing in xmlclass refactoring
Laurent Bessard
parents:
1291
diff
changeset
|
968 |
self.AddToLookupClass(name, parent, DefaultElementClass) |
40117d02601b
Fixed diagram editing in xmlclass refactoring
Laurent Bessard
parents:
1291
diff
changeset
|
969 |
elif namespace == self.TargetNamespace: |
40117d02601b
Fixed diagram editing in xmlclass refactoring
Laurent Bessard
parents:
1291
diff
changeset
|
970 |
self.AddToLookupClass(name, parent, type_name) |
814 | 971 |
if infos["type"] == COMPLEXTYPE: |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
972 |
type_name, parent = self.SplitQualifiedName(type_name, namespace) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
973 |
result = self.CreateClass(type_name, parent, infos) |
814 | 974 |
if result is not None and not isinstance(result, (UnicodeType, StringType)): |
975 |
self.Namespaces[self.TargetNamespace][result["name"]] = result |
|
976 |
return result |
|
977 |
elif infos["type"] == ELEMENT and infos["elmt_type"]["type"] == COMPLEXTYPE: |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
978 |
type_name, parent = self.SplitQualifiedName(type_name, namespace) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
979 |
result = self.CreateClass(type_name, parent, infos["elmt_type"]) |
814 | 980 |
if result is not None and not isinstance(result, (UnicodeType, StringType)): |
981 |
self.Namespaces[self.TargetNamespace][result["name"]] = result |
|
982 |
return result |
|
983 |
else: |
|
984 |
return infos |
|
985 |
elif typeinfos["type"] == COMPLEXTYPE: |
|
986 |
return self.CreateClass(name, parent, typeinfos) |
|
987 |
elif typeinfos["type"] == SIMPLETYPE: |
|
988 |
return typeinfos |
|
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
989 |
|
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
990 |
def GetEquivalentParents(self, parent): |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
991 |
return reduce(lambda x, y: x + y, |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
992 |
[[p] + self.GetEquivalentParents(p) |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
993 |
for p in self.EquivalentClassesParent.get(parent, {}).keys()], []) |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
994 |
|
814 | 995 |
""" |
996 |
Methods that generates the classes |
|
997 |
""" |
|
998 |
def CreateClasses(self): |
|
999 |
self.ParseSchema() |
|
1000 |
for name, infos in self.Namespaces[self.TargetNamespace].items(): |
|
1001 |
if infos["type"] == ELEMENT: |
|
1002 |
if not isinstance(infos["elmt_type"], (UnicodeType, StringType)) and \ |
|
1003 |
infos["elmt_type"]["type"] == COMPLEXTYPE: |
|
1004 |
self.ComputeAfter.append((name, None, infos["elmt_type"], True)) |
|
1005 |
while len(self.ComputeAfter) > 0: |
|
1006 |
result = self.CreateClass(*self.ComputeAfter.pop(0)) |
|
1007 |
if result is not None and not isinstance(result, (UnicodeType, StringType)): |
|
1008 |
self.Namespaces[self.TargetNamespace][result["name"]] = result |
|
1009 |
elif infos["type"] == COMPLEXTYPE: |
|
1010 |
self.ComputeAfter.append((name, None, infos)) |
|
1011 |
while len(self.ComputeAfter) > 0: |
|
1012 |
result = self.CreateClass(*self.ComputeAfter.pop(0)) |
|
1013 |
if result is not None and \ |
|
1014 |
not isinstance(result, (UnicodeType, StringType)): |
|
1015 |
self.Namespaces[self.TargetNamespace][result["name"]] = result |
|
1016 |
elif infos["type"] == ELEMENTSGROUP: |
|
1017 |
elements = [] |
|
1018 |
if infos.has_key("elements"): |
|
1019 |
elements = infos["elements"] |
|
1020 |
elif infos.has_key("choices"): |
|
1021 |
elements = infos["choices"] |
|
1022 |
for element in elements: |
|
1023 |
if not isinstance(element["elmt_type"], (UnicodeType, StringType)) and \ |
|
1024 |
element["elmt_type"]["type"] == COMPLEXTYPE: |
|
1025 |
self.ComputeAfter.append((element["name"], infos["name"], element["elmt_type"])) |
|
1026 |
while len(self.ComputeAfter) > 0: |
|
1027 |
result = self.CreateClass(*self.ComputeAfter.pop(0)) |
|
1028 |
if result is not None and \ |
|
1029 |
not isinstance(result, (UnicodeType, StringType)): |
|
1030 |
self.Namespaces[self.TargetNamespace][result["name"]] = result |
|
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1031 |
|
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1032 |
for name, parents in self.ComputedClassesLookUp.iteritems(): |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1033 |
if isinstance(parents, DictType): |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1034 |
computed_classes = parents.items() |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1035 |
elif parents[1] is not None: |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1036 |
computed_classes = [(self.etreeNamespaceFormat % parents[1], parents[0])] |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1037 |
else: |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1038 |
computed_classes = [] |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1039 |
for parent, computed_class in computed_classes: |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1040 |
for equivalent_parent in self.GetEquivalentParents(parent): |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1041 |
if not isinstance(parents, DictType): |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1042 |
parents = dict(computed_classes) |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1043 |
self.ComputedClassesLookUp[name] = parents |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1044 |
parents[equivalent_parent] = computed_class |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1045 |
|
814 | 1046 |
return self.ComputedClasses |
1047 |
||
1048 |
def CreateClass(self, name, parent, classinfos, baseclass = False): |
|
1049 |
if parent is not None: |
|
1050 |
classname = "%s_%s" % (parent, name) |
|
1051 |
else: |
|
1052 |
classname = name |
|
1053 |
||
1054 |
# Checks that classe haven't been generated yet |
|
1055 |
if self.AlreadyComputed.get(classname, False): |
|
1056 |
if baseclass: |
|
1057 |
self.AlreadyComputed[classname].IsBaseClass = baseclass |
|
1058 |
return self.ComputedClassesInfos.get(classname, None) |
|
1059 |
||
1060 |
# If base classes haven't been generated |
|
1061 |
bases = [] |
|
1062 |
base_infos = classinfos.get("base", None) |
|
1063 |
if base_infos is not None: |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1064 |
namespace, base_name = DecomposeQualifiedName(base_infos) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1065 |
if namespace == self.TargetNamespace: |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1066 |
self.AddEquivalentClass(name, base_name) |
814 | 1067 |
result = self.ExtractTypeInfos("base", name, base_infos) |
1068 |
if result is None: |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1069 |
namespace, base_name = DecomposeQualifiedName(base_infos) |
814 | 1070 |
if self.AlreadyComputed.get(base_name, False): |
1071 |
self.ComputeAfter.append((name, parent, classinfos)) |
|
1072 |
if self.TargetNamespace is not None: |
|
1073 |
return "%s:%s" % (self.TargetNamespace, classname) |
|
1074 |
else: |
|
1075 |
return classname |
|
1076 |
elif result is not None: |
|
1077 |
if self.FileName is not None: |
|
1078 |
classinfos["base"] = self.ComputedClasses[self.FileName].get(result["name"], None) |
|
1079 |
if classinfos["base"] is None: |
|
1080 |
for filename, classes in self.ComputedClasses.iteritems(): |
|
1081 |
if filename != self.FileName: |
|
1082 |
classinfos["base"] = classes.get(result["name"], None) |
|
1083 |
if classinfos["base"] is not None: |
|
1084 |
break |
|
1085 |
else: |
|
1086 |
classinfos["base"] = self.ComputedClasses.get(result["name"], None) |
|
1087 |
if classinfos["base"] is None: |
|
1088 |
raise ValueError("No class found for base type") |
|
1089 |
bases.append(classinfos["base"]) |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1090 |
bases.append(DefaultElementClass) |
814 | 1091 |
bases = tuple(bases) |
1092 |
classmembers = {"__doc__": classinfos.get("doc", ""), "IsBaseClass": baseclass} |
|
1093 |
||
1094 |
self.AlreadyComputed[classname] = True |
|
1095 |
||
1096 |
for attribute in classinfos["attributes"]: |
|
1097 |
infos = self.ExtractTypeInfos(attribute["name"], name, attribute["attr_type"]) |
|
1098 |
if infos is not None: |
|
1099 |
if infos["type"] != SIMPLETYPE: |
|
1100 |
raise ValueError("\"%s\" type is not a simple type!" % attribute["attr_type"]) |
|
1101 |
attrname = attribute["name"] |
|
1102 |
if attribute["use"] == "optional": |
|
1103 |
classmembers["add%s"%attrname] = generateAddMethod(attrname, self, attribute) |
|
1104 |
classmembers["delete%s"%attrname] = generateDeleteMethod(attrname) |
|
1105 |
classmembers["set%s"%attrname] = generateSetMethod(attrname) |
|
1106 |
classmembers["get%s"%attrname] = generateGetMethod(attrname) |
|
1107 |
else: |
|
1108 |
raise ValueError("\"%s\" type unrecognized!" % attribute["attr_type"]) |
|
1109 |
attribute["attr_type"] = infos |
|
1110 |
||
1111 |
for element in classinfos["elements"]: |
|
1112 |
if element["type"] == CHOICE: |
|
1113 |
elmtname = element["name"] |
|
1114 |
choices = ComputeContentChoices(self, name, element) |
|
1115 |
classmembers["get%schoices"%elmtname] = generateGetChoicesMethod(element["choices"]) |
|
1116 |
if element["maxOccurs"] == "unbounded" or element["maxOccurs"] > 1: |
|
1117 |
classmembers["append%sbytype" % elmtname] = generateAppendChoiceByTypeMethod(element["maxOccurs"], self, element["choices"]) |
|
1118 |
classmembers["insert%sbytype" % elmtname] = generateInsertChoiceByTypeMethod(element["maxOccurs"], self, element["choices"]) |
|
1119 |
else: |
|
1120 |
classmembers["set%sbytype" % elmtname] = generateSetChoiceByTypeMethod(self, element["choices"]) |
|
1121 |
infos = GenerateContentInfos(self, name, choices) |
|
1122 |
elif element["type"] == ANY: |
|
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1123 |
elmtname = element["name"] = "anyText" |
814 | 1124 |
element["minOccurs"] = element["maxOccurs"] = 1 |
1125 |
infos = GenerateAnyInfos(element) |
|
1126 |
else: |
|
1127 |
elmtname = element["name"] |
|
1128 |
if element["elmt_type"] == "tag": |
|
1129 |
infos = GenerateTagInfos(element) |
|
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1130 |
self.AddToLookupClass(element["name"], name, DefaultElementClass) |
814 | 1131 |
else: |
1132 |
infos = self.ExtractTypeInfos(element["name"], name, element["elmt_type"]) |
|
1133 |
if infos is not None: |
|
1134 |
element["elmt_type"] = infos |
|
1135 |
if element["maxOccurs"] == "unbounded" or element["maxOccurs"] > 1: |
|
1136 |
classmembers["append%s" % elmtname] = generateAppendMethod(elmtname, element["maxOccurs"], self, element) |
|
1137 |
classmembers["insert%s" % elmtname] = generateInsertMethod(elmtname, element["maxOccurs"], self, element) |
|
1138 |
classmembers["remove%s" % elmtname] = generateRemoveMethod(elmtname, element["minOccurs"]) |
|
1139 |
classmembers["count%s" % elmtname] = generateCountMethod(elmtname) |
|
1140 |
else: |
|
1141 |
if element["minOccurs"] == 0: |
|
1142 |
classmembers["add%s" % elmtname] = generateAddMethod(elmtname, self, element) |
|
1143 |
classmembers["delete%s" % elmtname] = generateDeleteMethod(elmtname) |
|
1144 |
classmembers["set%s" % elmtname] = generateSetMethod(elmtname) |
|
1145 |
classmembers["get%s" % elmtname] = generateGetMethod(elmtname) |
|
1146 |
||
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
1147 |
classmembers["_init_"] = generateInitMethod(self, classinfos) |
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1148 |
classmembers["StructurePattern"] = GetStructurePattern(classinfos) |
814 | 1149 |
classmembers["getElementAttributes"] = generateGetElementAttributes(self, classinfos) |
1150 |
classmembers["getElementInfos"] = generateGetElementInfos(self, classinfos) |
|
1151 |
classmembers["setElementValue"] = generateSetElementValue(self, classinfos) |
|
1152 |
||
1153 |
class_definition = classobj(str(classname), bases, classmembers) |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1154 |
setattr(class_definition, "__getattr__", generateGetattrMethod(self, class_definition, classinfos)) |
814 | 1155 |
setattr(class_definition, "__setattr__", generateSetattrMethod(self, class_definition, classinfos)) |
1156 |
class_infos = {"type": COMPILEDCOMPLEXTYPE, |
|
1157 |
"name": classname, |
|
1158 |
"initial": generateClassCreateFunction(class_definition), |
|
1303
908a5803c2cc
Removed obsolete functions for extracting values for xml dom tree and generating xml string
Laurent Bessard
parents:
1300
diff
changeset
|
1159 |
} |
814 | 1160 |
|
1161 |
if self.FileName is not None: |
|
1162 |
self.ComputedClasses[self.FileName][classname] = class_definition |
|
1163 |
else: |
|
1164 |
self.ComputedClasses[classname] = class_definition |
|
1165 |
self.ComputedClassesInfos[classname] = class_infos |
|
1166 |
||
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1167 |
self.AddToLookupClass(name, parent, class_definition) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1168 |
self.AddToLookupClass(classname, None, class_definition) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1169 |
|
814 | 1170 |
return class_infos |
1171 |
||
1172 |
""" |
|
1173 |
Methods that print the classes generated |
|
1174 |
""" |
|
1175 |
def PrintClasses(self): |
|
1176 |
items = self.ComputedClasses.items() |
|
1177 |
items.sort() |
|
1178 |
if self.FileName is not None: |
|
1179 |
for filename, classes in items: |
|
1180 |
print "File '%s':" % filename |
|
1181 |
class_items = classes.items() |
|
1182 |
class_items.sort() |
|
1183 |
for classname, xmlclass in class_items: |
|
1184 |
print "%s: %s" % (classname, str(xmlclass)) |
|
1185 |
else: |
|
1186 |
for classname, xmlclass in items: |
|
1187 |
print "%s: %s" % (classname, str(xmlclass)) |
|
1188 |
||
1189 |
def PrintClassNames(self): |
|
1190 |
classnames = self.XMLClassDefinitions.keys() |
|
1191 |
classnames.sort() |
|
1192 |
for classname in classnames: |
|
1193 |
print classname |
|
1194 |
||
1195 |
""" |
|
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1196 |
Method that generate the method for generating the xml tree structure model by |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1197 |
following the attributes list defined |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1198 |
""" |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1199 |
def ComputeMultiplicity(name, infos): |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1200 |
if infos["minOccurs"] == 0: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1201 |
if infos["maxOccurs"] == "unbounded": |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1202 |
return "(?:%s)*" % name |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1203 |
elif infos["maxOccurs"] == 1: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1204 |
return "(?:%s)?" % name |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1205 |
else: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1206 |
return "(?:%s){,%d}" % (name, infos["maxOccurs"]) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1207 |
elif infos["minOccurs"] == 1: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1208 |
if infos["maxOccurs"] == "unbounded": |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1209 |
return "(?:%s)+" % name |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1210 |
elif infos["maxOccurs"] == 1: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1211 |
return "(?:%s)" % name |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1212 |
else: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1213 |
return "(?:%s){1,%d}" % (name, infos["maxOccurs"]) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1214 |
else: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1215 |
if infos["maxOccurs"] == "unbounded": |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1216 |
return "(?:%s){%d,}" % (name, infos["minOccurs"], name) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1217 |
else: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1218 |
return "(?:%s){%d,%d}" % (name, infos["minOccurs"], |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1219 |
infos["maxOccurs"]) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1220 |
|
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1221 |
def GetStructurePattern(classinfos): |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1222 |
base_structure_pattern = ( |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1223 |
classinfos["base"].StructurePattern.pattern[:-1] |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1224 |
if classinfos.has_key("base") else "") |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1225 |
elements = [] |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1226 |
for element in classinfos["elements"]: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1227 |
if element["type"] == ANY: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1228 |
infos = element.copy() |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1229 |
infos["minOccurs"] = 0 |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1230 |
elements.append(ComputeMultiplicity("#text |#cdata-section |\w* ", infos)) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1231 |
elif element["type"] == CHOICE: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1232 |
choices = [] |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1233 |
for infos in element["choices"]: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1234 |
if infos["type"] == "sequence": |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1235 |
structure = "(?:%s)" % GetStructurePattern(infos) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1236 |
else: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1237 |
structure = "%s " % infos["name"] |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1238 |
choices.append(ComputeMultiplicity(structure, infos)) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1239 |
elements.append(ComputeMultiplicity("|".join(choices), element)) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1240 |
elif element["name"] == "content" and element["elmt_type"]["type"] == SIMPLETYPE: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1241 |
elements.append("(?:#text |#cdata-section )?") |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1242 |
else: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1243 |
elements.append(ComputeMultiplicity("%s " % element["name"], element)) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1244 |
if classinfos.get("order", True) or len(elements) == 0: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1245 |
return re.compile(base_structure_pattern + "".join(elements) + "$") |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1246 |
else: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1247 |
raise ValueError("XSD structure not yet supported!") |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1248 |
|
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1249 |
""" |
814 | 1250 |
Method that generate the method for creating a class instance |
1251 |
""" |
|
1252 |
def generateClassCreateFunction(class_definition): |
|
1253 |
def classCreatefunction(): |
|
1254 |
return class_definition() |
|
1255 |
return classCreatefunction |
|
1256 |
||
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1257 |
def generateGetattrMethod(factory, class_definition, classinfos): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1258 |
attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"]) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1259 |
optional_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "optional"]) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1260 |
elements = dict([(element["name"], element) for element in classinfos["elements"]]) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1261 |
|
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1262 |
def getattrMethod(self, name): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1263 |
if attributes.has_key(name): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1264 |
attribute_infos = attributes[name] |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1265 |
attribute_infos["attr_type"] = FindTypeInfos(factory, attribute_infos["attr_type"]) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1266 |
value = self.get(name) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1267 |
if value is not None: |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1268 |
return attribute_infos["attr_type"]["extract"](value, extract=False) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1269 |
elif attribute_infos.has_key("fixed"): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1270 |
return attribute_infos["attr_type"]["extract"](attribute_infos["fixed"], extract=False) |
1294
f02ba5b83811
Fixed datatype and configuration editing in xmlclass refactoring
Laurent Bessard
parents:
1293
diff
changeset
|
1271 |
elif attribute_infos.has_key("default"): |
f02ba5b83811
Fixed datatype and configuration editing in xmlclass refactoring
Laurent Bessard
parents:
1293
diff
changeset
|
1272 |
return attribute_infos["attr_type"]["extract"](attribute_infos["default"], extract=False) |
f02ba5b83811
Fixed datatype and configuration editing in xmlclass refactoring
Laurent Bessard
parents:
1293
diff
changeset
|
1273 |
return None |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1274 |
|
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1275 |
elif elements.has_key(name): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1276 |
element_infos = elements[name] |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1277 |
element_infos["elmt_type"] = FindTypeInfos(factory, element_infos["elmt_type"]) |
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1278 |
if element_infos["type"] == CHOICE: |
1305
714f1381a09a
Fixed xmlclass and plcopen using precompile xpath where possible
Laurent Bessard
parents:
1304
diff
changeset
|
1279 |
content = element_infos["elmt_type"]["choices_xpath"](self) |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1280 |
if element_infos["maxOccurs"] == "unbounded" or element_infos["maxOccurs"] > 1: |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1281 |
return content |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1282 |
elif len(content) > 0: |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1283 |
return content[0] |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1284 |
return None |
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1285 |
elif element_infos["type"] == ANY: |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1286 |
return element_infos["elmt_type"]["extract"](self) |
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1287 |
elif name == "content" and element_infos["elmt_type"]["type"] == SIMPLETYPE: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1288 |
return element_infos["elmt_type"]["extract"](self.text, extract=False) |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1289 |
else: |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1290 |
element_name = factory.etreeNamespaceFormat % name |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1291 |
if element_infos["maxOccurs"] == "unbounded" or element_infos["maxOccurs"] > 1: |
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1292 |
values = self.findall(element_name) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1293 |
if element_infos["elmt_type"]["type"] == SIMPLETYPE: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1294 |
return map(lambda value: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1295 |
element_infos["elmt_type"]["extract"](value.text, extract=False), |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1296 |
values) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1297 |
return values |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1298 |
else: |
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1299 |
value = self.find(element_name) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1300 |
if element_infos["elmt_type"]["type"] == SIMPLETYPE: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1301 |
return element_infos["elmt_type"]["extract"](value.text, extract=False) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1302 |
return value |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1303 |
|
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1304 |
elif classinfos.has_key("base"): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1305 |
return classinfos["base"].__getattr__(self, name) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1306 |
|
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1307 |
return DefaultElementClass.__getattribute__(self, name) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1308 |
|
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1309 |
return getattrMethod |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1310 |
|
814 | 1311 |
def generateSetattrMethod(factory, class_definition, classinfos): |
1312 |
attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"]) |
|
1313 |
optional_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "optional"]) |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1314 |
elements = OrderedDict([(element["name"], element) for element in classinfos["elements"]]) |
814 | 1315 |
|
1316 |
def setattrMethod(self, name, value): |
|
1317 |
if attributes.has_key(name): |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1318 |
attribute_infos = attributes[name] |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1319 |
attribute_infos["attr_type"] = FindTypeInfos(factory, attribute_infos["attr_type"]) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1320 |
if optional_attributes.get(name, False): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1321 |
default = attribute_infos.get("default", None) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1322 |
if value is None or value == default: |
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1323 |
self.attrib.pop(name, None) |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1324 |
return |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1325 |
elif attribute_infos.has_key("fixed"): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1326 |
return |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1327 |
return self.set(name, attribute_infos["attr_type"]["generate"](value)) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1328 |
|
814 | 1329 |
elif elements.has_key(name): |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1330 |
element_infos = elements[name] |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1331 |
element_infos["elmt_type"] = FindTypeInfos(factory, element_infos["elmt_type"]) |
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1332 |
if element_infos["type"] == ANY: |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1333 |
element_infos["elmt_type"]["generate"](self, value) |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1334 |
|
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1335 |
elif name == "content" and element_infos["elmt_type"]["type"] == SIMPLETYPE: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1336 |
self.text = element_infos["elmt_type"]["generate"](value) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1337 |
|
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1338 |
else: |
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
1339 |
prefix = ("%s:" % factory.TargetNamespace |
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
1340 |
if factory.TargetNamespace is not None else "") |
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
1341 |
element_xpath = (prefix + name |
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1342 |
if name != "content" |
1305
714f1381a09a
Fixed xmlclass and plcopen using precompile xpath where possible
Laurent Bessard
parents:
1304
diff
changeset
|
1343 |
else elements["content"]["elmt_type"]["choices_xpath"].path) |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1344 |
|
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1345 |
for element in self.xpath(element_xpath, namespaces=factory.NSMAP): |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1346 |
self.remove(element) |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1347 |
|
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1348 |
if value is not None: |
1294
f02ba5b83811
Fixed datatype and configuration editing in xmlclass refactoring
Laurent Bessard
parents:
1293
diff
changeset
|
1349 |
element_idx = elements.keys().index(name) |
f02ba5b83811
Fixed datatype and configuration editing in xmlclass refactoring
Laurent Bessard
parents:
1293
diff
changeset
|
1350 |
if element_idx > 0: |
f02ba5b83811
Fixed datatype and configuration editing in xmlclass refactoring
Laurent Bessard
parents:
1293
diff
changeset
|
1351 |
previous_elements_xpath = "|".join(map( |
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
1352 |
lambda x: prefix + x |
1294
f02ba5b83811
Fixed datatype and configuration editing in xmlclass refactoring
Laurent Bessard
parents:
1293
diff
changeset
|
1353 |
if x != "content" |
1305
714f1381a09a
Fixed xmlclass and plcopen using precompile xpath where possible
Laurent Bessard
parents:
1304
diff
changeset
|
1354 |
else elements["content"]["elmt_type"]["choices_xpath"].path, |
1294
f02ba5b83811
Fixed datatype and configuration editing in xmlclass refactoring
Laurent Bessard
parents:
1293
diff
changeset
|
1355 |
elements.keys()[:element_idx])) |
f02ba5b83811
Fixed datatype and configuration editing in xmlclass refactoring
Laurent Bessard
parents:
1293
diff
changeset
|
1356 |
|
f02ba5b83811
Fixed datatype and configuration editing in xmlclass refactoring
Laurent Bessard
parents:
1293
diff
changeset
|
1357 |
insertion_point = len(self.xpath(previous_elements_xpath, namespaces=factory.NSMAP)) |
f02ba5b83811
Fixed datatype and configuration editing in xmlclass refactoring
Laurent Bessard
parents:
1293
diff
changeset
|
1358 |
else: |
f02ba5b83811
Fixed datatype and configuration editing in xmlclass refactoring
Laurent Bessard
parents:
1293
diff
changeset
|
1359 |
insertion_point = 0 |
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1360 |
|
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1361 |
if not isinstance(value, ListType): |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1362 |
value = [value] |
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1363 |
|
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1364 |
for element in reversed(value): |
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1365 |
if element_infos["elmt_type"]["type"] == SIMPLETYPE: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1366 |
tmp_element = etree.Element(factory.etreeNamespaceFormat % name) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1367 |
tmp_element.text = element_infos["elmt_type"]["generate"](element) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1368 |
element = tmp_element |
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1369 |
self.insert(insertion_point, element) |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1370 |
|
814 | 1371 |
elif classinfos.has_key("base"): |
1372 |
return classinfos["base"].__setattr__(self, name, value) |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1373 |
|
814 | 1374 |
else: |
1375 |
raise AttributeError("'%s' can't have an attribute '%s'." % (self.__class__.__name__, name)) |
|
1376 |
||
1377 |
return setattrMethod |
|
1378 |
||
1379 |
def gettypeinfos(name, facets): |
|
1380 |
if facets.has_key("enumeration") and facets["enumeration"][0] is not None: |
|
1381 |
return facets["enumeration"][0] |
|
1382 |
elif facets.has_key("maxInclusive"): |
|
1383 |
limits = {"max" : None, "min" : None} |
|
1384 |
if facets["maxInclusive"][0] is not None: |
|
1385 |
limits["max"] = facets["maxInclusive"][0] |
|
1386 |
elif facets["maxExclusive"][0] is not None: |
|
1387 |
limits["max"] = facets["maxExclusive"][0] - 1 |
|
1388 |
if facets["minInclusive"][0] is not None: |
|
1389 |
limits["min"] = facets["minInclusive"][0] |
|
1390 |
elif facets["minExclusive"][0] is not None: |
|
1391 |
limits["min"] = facets["minExclusive"][0] + 1 |
|
1392 |
if limits["max"] is not None or limits["min"] is not None: |
|
1393 |
return limits |
|
1394 |
return name |
|
1395 |
||
1396 |
def generateGetElementAttributes(factory, classinfos): |
|
1397 |
def getElementAttributes(self): |
|
1398 |
attr_list = [] |
|
1399 |
if classinfos.has_key("base"): |
|
1400 |
attr_list.extend(classinfos["base"].getElementAttributes(self)) |
|
1401 |
for attr in classinfos["attributes"]: |
|
1402 |
if attr["use"] != "prohibited": |
|
1403 |
attr_params = {"name" : attr["name"], "use" : attr["use"], |
|
1404 |
"type" : gettypeinfos(attr["attr_type"]["basename"], attr["attr_type"]["facets"]), |
|
1405 |
"value" : getattr(self, attr["name"], "")} |
|
1406 |
attr_list.append(attr_params) |
|
1407 |
return attr_list |
|
1408 |
return getElementAttributes |
|
1409 |
||
1410 |
def generateGetElementInfos(factory, classinfos): |
|
1411 |
attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"]) |
|
1412 |
elements = dict([(element["name"], element) for element in classinfos["elements"]]) |
|
1413 |
||
1414 |
def getElementInfos(self, name, path=None, derived=False): |
|
1415 |
attr_type = "element" |
|
1416 |
value = None |
|
1417 |
use = "required" |
|
1418 |
children = [] |
|
1419 |
if path is not None: |
|
1420 |
parts = path.split(".", 1) |
|
1421 |
if attributes.has_key(parts[0]): |
|
1179
3e7bd88fcff7
Fixed inconsistency in value display when setting integer value for float parameter
Laurent Bessard
parents:
1124
diff
changeset
|
1422 |
if len(parts) != 1: |
814 | 1423 |
raise ValueError("Wrong path!") |
1424 |
attr_type = gettypeinfos(attributes[parts[0]]["attr_type"]["basename"], |
|
1425 |
attributes[parts[0]]["attr_type"]["facets"]) |
|
1426 |
value = getattr(self, parts[0], "") |
|
1427 |
elif elements.has_key(parts[0]): |
|
1428 |
if elements[parts[0]]["elmt_type"]["type"] == SIMPLETYPE: |
|
1179
3e7bd88fcff7
Fixed inconsistency in value display when setting integer value for float parameter
Laurent Bessard
parents:
1124
diff
changeset
|
1429 |
if len(parts) != 1: |
814 | 1430 |
raise ValueError("Wrong path!") |
1431 |
attr_type = gettypeinfos(elements[parts[0]]["elmt_type"]["basename"], |
|
1432 |
elements[parts[0]]["elmt_type"]["facets"]) |
|
1433 |
value = getattr(self, parts[0], "") |
|
1434 |
elif parts[0] == "content": |
|
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
1435 |
return self.content.getElementInfos(self.content.getLocalTag(), path) |
814 | 1436 |
else: |
1437 |
attr = getattr(self, parts[0], None) |
|
1438 |
if attr is None: |
|
1439 |
raise ValueError("Wrong path!") |
|
1440 |
if len(parts) == 1: |
|
1441 |
return attr.getElementInfos(parts[0]) |
|
1442 |
else: |
|
1443 |
return attr.getElementInfos(parts[0], parts[1]) |
|
1179
3e7bd88fcff7
Fixed inconsistency in value display when setting integer value for float parameter
Laurent Bessard
parents:
1124
diff
changeset
|
1444 |
elif elements.has_key("content"): |
3e7bd88fcff7
Fixed inconsistency in value display when setting integer value for float parameter
Laurent Bessard
parents:
1124
diff
changeset
|
1445 |
if len(parts) > 0: |
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
1446 |
return self.content.getElementInfos(name, path) |
1179
3e7bd88fcff7
Fixed inconsistency in value display when setting integer value for float parameter
Laurent Bessard
parents:
1124
diff
changeset
|
1447 |
elif classinfos.has_key("base"): |
3e7bd88fcff7
Fixed inconsistency in value display when setting integer value for float parameter
Laurent Bessard
parents:
1124
diff
changeset
|
1448 |
classinfos["base"].getElementInfos(name, path) |
814 | 1449 |
else: |
1450 |
raise ValueError("Wrong path!") |
|
1451 |
else: |
|
1452 |
if not derived: |
|
1453 |
children.extend(self.getElementAttributes()) |
|
1454 |
if classinfos.has_key("base"): |
|
1455 |
children.extend(classinfos["base"].getElementInfos(self, name, derived=True)["children"]) |
|
1456 |
for element_name, element in elements.items(): |
|
1457 |
if element["minOccurs"] == 0: |
|
1458 |
use = "optional" |
|
1459 |
if element_name == "content" and element["type"] == CHOICE: |
|
1460 |
attr_type = [(choice["name"], None) for choice in element["choices"]] |
|
1461 |
if self.content is None: |
|
1462 |
value = "" |
|
1463 |
else: |
|
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
1464 |
value = self.content.getLocalTag() |
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
1465 |
if self.content is not None: |
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
1466 |
children.extend(self.content.getElementInfos(value)["children"]) |
814 | 1467 |
elif element["elmt_type"]["type"] == SIMPLETYPE: |
1468 |
children.append({"name": element_name, "require": element["minOccurs"] != 0, |
|
1469 |
"type": gettypeinfos(element["elmt_type"]["basename"], |
|
1470 |
element["elmt_type"]["facets"]), |
|
1471 |
"value": getattr(self, element_name, None)}) |
|
1472 |
else: |
|
1473 |
instance = getattr(self, element_name, None) |
|
1474 |
if instance is None: |
|
1475 |
instance = element["elmt_type"]["initial"]() |
|
1476 |
children.append(instance.getElementInfos(element_name)) |
|
1477 |
return {"name": name, "type": attr_type, "value": value, "use": use, "children": children} |
|
1478 |
return getElementInfos |
|
1479 |
||
1480 |
def generateSetElementValue(factory, classinfos): |
|
1481 |
attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"]) |
|
1482 |
elements = dict([(element["name"], element) for element in classinfos["elements"]]) |
|
1483 |
||
1484 |
def setElementValue(self, path, value): |
|
1485 |
if path is not None: |
|
1486 |
parts = path.split(".", 1) |
|
1487 |
if attributes.has_key(parts[0]): |
|
1488 |
if len(parts) != 1: |
|
1489 |
raise ValueError("Wrong path!") |
|
1490 |
if attributes[parts[0]]["attr_type"]["basename"] == "boolean": |
|
1491 |
setattr(self, parts[0], value) |
|
1017
2925d6e49893
Fixed bug when setting empty value to optional non-string parameters
Laurent Bessard
parents:
814
diff
changeset
|
1492 |
elif attributes[parts[0]]["use"] == "optional" and value == "": |
1022
ec30c12b1d67
Fixed bug when connecting and URI_location is empty
Laurent Bessard
parents:
1017
diff
changeset
|
1493 |
if attributes[parts[0]].has_key("default"): |
ec30c12b1d67
Fixed bug when connecting and URI_location is empty
Laurent Bessard
parents:
1017
diff
changeset
|
1494 |
setattr(self, parts[0], |
ec30c12b1d67
Fixed bug when connecting and URI_location is empty
Laurent Bessard
parents:
1017
diff
changeset
|
1495 |
attributes[parts[0]]["attr_type"]["extract"]( |
ec30c12b1d67
Fixed bug when connecting and URI_location is empty
Laurent Bessard
parents:
1017
diff
changeset
|
1496 |
attributes[parts[0]]["default"], False)) |
ec30c12b1d67
Fixed bug when connecting and URI_location is empty
Laurent Bessard
parents:
1017
diff
changeset
|
1497 |
else: |
ec30c12b1d67
Fixed bug when connecting and URI_location is empty
Laurent Bessard
parents:
1017
diff
changeset
|
1498 |
setattr(self, parts[0], None) |
814 | 1499 |
else: |
1500 |
setattr(self, parts[0], attributes[parts[0]]["attr_type"]["extract"](value, False)) |
|
1501 |
elif elements.has_key(parts[0]): |
|
1502 |
if elements[parts[0]]["elmt_type"]["type"] == SIMPLETYPE: |
|
1503 |
if len(parts) != 1: |
|
1504 |
raise ValueError("Wrong path!") |
|
1505 |
if elements[parts[0]]["elmt_type"]["basename"] == "boolean": |
|
1506 |
setattr(self, parts[0], value) |
|
1017
2925d6e49893
Fixed bug when setting empty value to optional non-string parameters
Laurent Bessard
parents:
814
diff
changeset
|
1507 |
elif attributes[parts[0]]["minOccurs"] == 0 and value == "": |
2925d6e49893
Fixed bug when setting empty value to optional non-string parameters
Laurent Bessard
parents:
814
diff
changeset
|
1508 |
setattr(self, parts[0], None) |
814 | 1509 |
else: |
1510 |
setattr(self, parts[0], elements[parts[0]]["elmt_type"]["extract"](value, False)) |
|
1511 |
else: |
|
1512 |
instance = getattr(self, parts[0], None) |
|
1513 |
if instance is None and elements[parts[0]]["minOccurs"] == 0: |
|
1514 |
instance = elements[parts[0]]["elmt_type"]["initial"]() |
|
1515 |
setattr(self, parts[0], instance) |
|
1516 |
if instance != None: |
|
1517 |
if len(parts) > 1: |
|
1518 |
instance.setElementValue(parts[1], value) |
|
1519 |
else: |
|
1520 |
instance.setElementValue(None, value) |
|
1521 |
elif elements.has_key("content"): |
|
1522 |
if len(parts) > 0: |
|
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
1523 |
self.content.setElementValue(path, value) |
814 | 1524 |
elif classinfos.has_key("base"): |
1525 |
classinfos["base"].setElementValue(self, path, value) |
|
1526 |
elif elements.has_key("content"): |
|
1527 |
if value == "": |
|
1528 |
if elements["content"]["minOccurs"] == 0: |
|
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
1529 |
self.setcontent([]) |
814 | 1530 |
else: |
1531 |
raise ValueError("\"content\" element is required!") |
|
1532 |
else: |
|
1533 |
self.setcontentbytype(value) |
|
1534 |
return setElementValue |
|
1535 |
||
1536 |
""" |
|
1537 |
Methods that generates the different methods for setting and getting the attributes |
|
1538 |
""" |
|
1539 |
def generateInitMethod(factory, classinfos): |
|
1540 |
def initMethod(self): |
|
1541 |
if classinfos.has_key("base"): |
|
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
1542 |
classinfos["base"]._init_(self) |
814 | 1543 |
for attribute in classinfos["attributes"]: |
1544 |
attribute["attr_type"] = FindTypeInfos(factory, attribute["attr_type"]) |
|
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1545 |
if attribute["use"] == "required": |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1546 |
self.set(attribute["name"], attribute["attr_type"]["generate"](attribute["attr_type"]["initial"]())) |
814 | 1547 |
for element in classinfos["elements"]: |
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1548 |
if element["type"] != CHOICE: |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1549 |
element_name = ( |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1550 |
etree.QName(factory.NSMAP["xhtml"], "p") |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1551 |
if element["type"] == ANY |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1552 |
else factory.etreeNamespaceFormat % element["name"]) |
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1553 |
initial = GetElementInitialValue(factory, element) |
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1554 |
if initial is not None: |
1293
40117d02601b
Fixed diagram editing in xmlclass refactoring
Laurent Bessard
parents:
1291
diff
changeset
|
1555 |
map(self.append, initial) |
814 | 1556 |
return initMethod |
1557 |
||
1558 |
def generateSetMethod(attr): |
|
1559 |
def setMethod(self, value): |
|
1560 |
setattr(self, attr, value) |
|
1561 |
return setMethod |
|
1562 |
||
1563 |
def generateGetMethod(attr): |
|
1564 |
def getMethod(self): |
|
1565 |
return getattr(self, attr, None) |
|
1566 |
return getMethod |
|
1567 |
||
1568 |
def generateAddMethod(attr, factory, infos): |
|
1569 |
def addMethod(self): |
|
1570 |
if infos["type"] == ATTRIBUTE: |
|
1571 |
infos["attr_type"] = FindTypeInfos(factory, infos["attr_type"]) |
|
1293
40117d02601b
Fixed diagram editing in xmlclass refactoring
Laurent Bessard
parents:
1291
diff
changeset
|
1572 |
if not infos.has_key("default"): |
40117d02601b
Fixed diagram editing in xmlclass refactoring
Laurent Bessard
parents:
1291
diff
changeset
|
1573 |
setattr(self, attr, infos["attr_type"]["initial"]()) |
814 | 1574 |
elif infos["type"] == ELEMENT: |
1575 |
infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"]) |
|
1293
40117d02601b
Fixed diagram editing in xmlclass refactoring
Laurent Bessard
parents:
1291
diff
changeset
|
1576 |
value = infos["elmt_type"]["initial"]() |
40117d02601b
Fixed diagram editing in xmlclass refactoring
Laurent Bessard
parents:
1291
diff
changeset
|
1577 |
DefaultElementClass.__setattr__(value, "tag", factory.etreeNamespaceFormat % attr) |
40117d02601b
Fixed diagram editing in xmlclass refactoring
Laurent Bessard
parents:
1291
diff
changeset
|
1578 |
setattr(self, attr, value) |
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
1579 |
value._init_() |
814 | 1580 |
else: |
1581 |
raise ValueError("Invalid class attribute!") |
|
1582 |
return addMethod |
|
1583 |
||
1584 |
def generateDeleteMethod(attr): |
|
1585 |
def deleteMethod(self): |
|
1586 |
setattr(self, attr, None) |
|
1587 |
return deleteMethod |
|
1588 |
||
1589 |
def generateAppendMethod(attr, maxOccurs, factory, infos): |
|
1590 |
def appendMethod(self, value): |
|
1591 |
infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"]) |
|
1592 |
attr_list = getattr(self, attr) |
|
1593 |
if maxOccurs == "unbounded" or len(attr_list) < maxOccurs: |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1594 |
if len(attr_list) == 0: |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1595 |
setattr(self, attr, [value]) |
814 | 1596 |
else: |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1597 |
attr_list[-1].addnext(value) |
814 | 1598 |
else: |
1599 |
raise ValueError("There can't be more than %d values in \"%s\"!" % (maxOccurs, attr)) |
|
1600 |
return appendMethod |
|
1601 |
||
1602 |
def generateInsertMethod(attr, maxOccurs, factory, infos): |
|
1603 |
def insertMethod(self, index, value): |
|
1604 |
infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"]) |
|
1605 |
attr_list = getattr(self, attr) |
|
1606 |
if maxOccurs == "unbounded" or len(attr_list) < maxOccurs: |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1607 |
if len(attr_list) == 0: |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1608 |
setattr(self, attr, [value]) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1609 |
elif index == 0: |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1610 |
attr_list[0].addprevious(value) |
814 | 1611 |
else: |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1612 |
attr_list[min(index - 1, len(attr_list) - 1)].addnext(value) |
814 | 1613 |
else: |
1614 |
raise ValueError("There can't be more than %d values in \"%s\"!" % (maxOccurs, attr)) |
|
1615 |
return insertMethod |
|
1616 |
||
1617 |
def generateGetChoicesMethod(choice_types): |
|
1618 |
def getChoicesMethod(self): |
|
1619 |
return [choice["name"] for choice in choice_types] |
|
1620 |
return getChoicesMethod |
|
1621 |
||
1622 |
def generateSetChoiceByTypeMethod(factory, choice_types): |
|
1623 |
choices = dict([(choice["name"], choice) for choice in choice_types]) |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1624 |
def setChoiceMethod(self, content_type): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1625 |
if not choices.has_key(content_type): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1626 |
raise ValueError("Unknown \"%s\" choice type for \"content\"!" % content_type) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1627 |
choices[content_type]["elmt_type"] = FindTypeInfos(factory, choices[content_type]["elmt_type"]) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1628 |
new_content = choices[content_type]["elmt_type"]["initial"]() |
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
1629 |
DefaultElementClass.__setattr__(new_content, "tag", factory.etreeNamespaceFormat % content_type) |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1630 |
self.content = new_content |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1631 |
return new_content |
814 | 1632 |
return setChoiceMethod |
1633 |
||
1634 |
def generateAppendChoiceByTypeMethod(maxOccurs, factory, choice_types): |
|
1635 |
choices = dict([(choice["name"], choice) for choice in choice_types]) |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1636 |
def appendChoiceMethod(self, content_type): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1637 |
if not choices.has_key(content_type): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1638 |
raise ValueError("Unknown \"%s\" choice type for \"content\"!" % content_type) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1639 |
choices[content_type]["elmt_type"] = FindTypeInfos(factory, choices[content_type]["elmt_type"]) |
814 | 1640 |
if maxOccurs == "unbounded" or len(self.content) < maxOccurs: |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1641 |
new_element = choices[content_type]["elmt_type"]["initial"]() |
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
1642 |
DefaultElementClass.__setattr__(new_element, "tag", factory.etreeNamespaceFormat % content_type) |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1643 |
self.appendcontent(new_element) |
814 | 1644 |
return new_element |
1645 |
else: |
|
1646 |
raise ValueError("There can't be more than %d values in \"content\"!" % maxOccurs) |
|
1647 |
return appendChoiceMethod |
|
1648 |
||
1649 |
def generateInsertChoiceByTypeMethod(maxOccurs, factory, choice_types): |
|
1650 |
choices = dict([(choice["name"], choice) for choice in choice_types]) |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1651 |
def insertChoiceMethod(self, index, content_type): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1652 |
if not choices.has_key(content_type): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1653 |
raise ValueError("Unknown \"%s\" choice type for \"content\"!" % content_type) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1654 |
choices[type]["elmt_type"] = FindTypeInfos(factory, choices[content_type]["elmt_type"]) |
814 | 1655 |
if maxOccurs == "unbounded" or len(self.content) < maxOccurs: |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1656 |
new_element = choices[content_type]["elmt_type"]["initial"]() |
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
1657 |
DefaultElementClass.__setattr__(new_element, "tag", factory.etreeNamespaceFormat % content_type) |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1658 |
self.insertcontent(index, new_element) |
814 | 1659 |
return new_element |
1660 |
else: |
|
1661 |
raise ValueError("There can't be more than %d values in \"content\"!" % maxOccurs) |
|
1662 |
return insertChoiceMethod |
|
1663 |
||
1664 |
def generateRemoveMethod(attr, minOccurs): |
|
1665 |
def removeMethod(self, index): |
|
1666 |
attr_list = getattr(self, attr) |
|
1667 |
if len(attr_list) > minOccurs: |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1668 |
self.remove(attr_list[index]) |
814 | 1669 |
else: |
1670 |
raise ValueError("There can't be less than %d values in \"%s\"!" % (minOccurs, attr)) |
|
1671 |
return removeMethod |
|
1672 |
||
1673 |
def generateCountMethod(attr): |
|
1674 |
def countMethod(self): |
|
1675 |
return len(getattr(self, attr)) |
|
1676 |
return countMethod |
|
1677 |
||
1678 |
""" |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1679 |
This function generate a xml parser from a class factory |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1680 |
""" |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1681 |
|
1300
8e1ee07bdff8
Removed namespaces declaration in subtree elements xml description when copy/paste
Laurent Bessard
parents:
1294
diff
changeset
|
1682 |
NAMESPACE_PATTERN = re.compile("xmlns(?:\:[^\=]*)?=\"[^\"]*\" ") |
8e1ee07bdff8
Removed namespaces declaration in subtree elements xml description when copy/paste
Laurent Bessard
parents:
1294
diff
changeset
|
1683 |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1684 |
class DefaultElementClass(etree.ElementBase): |
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1685 |
|
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1686 |
StructurePattern = re.compile("$") |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1687 |
|
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
1688 |
def _init_(self): |
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1689 |
pass |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1690 |
|
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1691 |
def getLocalTag(self): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1692 |
return etree.QName(self.tag).localname |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1693 |
|
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1694 |
def tostring(self): |
1300
8e1ee07bdff8
Removed namespaces declaration in subtree elements xml description when copy/paste
Laurent Bessard
parents:
1294
diff
changeset
|
1695 |
return NAMESPACE_PATTERN.sub("", etree.tostring(self, pretty_print=True)) |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1696 |
|
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1697 |
class XMLElementClassLookUp(etree.PythonElementClassLookup): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1698 |
|
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1699 |
def __init__(self, classes, *args, **kwargs): |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1700 |
etree.PythonElementClassLookup.__init__(self, *args, **kwargs) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1701 |
self.LookUpClasses = classes |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1702 |
|
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1703 |
def GetElementClass(self, element_tag, parent_tag=None, default=DefaultElementClass): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1704 |
element_class = self.LookUpClasses.get(element_tag, (default, None)) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1705 |
if not isinstance(element_class, DictType): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1706 |
if isinstance(element_class[0], (StringType, UnicodeType)): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1707 |
return self.GetElementClass(element_class[0], default=default) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1708 |
return element_class[0] |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1709 |
|
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1710 |
element_with_parent_class = element_class.get(parent_tag, default) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1711 |
if isinstance(element_with_parent_class, (StringType, UnicodeType)): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1712 |
return self.GetElementClass(element_with_parent_class, default=default) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1713 |
return element_with_parent_class |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1714 |
|
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1715 |
def lookup(self, document, element): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1716 |
parent = element.getparent() |
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1717 |
element_class = self.GetElementClass(element.tag, |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1718 |
parent.tag if parent is not None else None) |
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1719 |
if isinstance(element_class, ListType): |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1720 |
children = "".join([ |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1721 |
"%s " % etree.QName(child.tag).localname |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1722 |
for child in element]) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1723 |
for possible_class in element_class: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1724 |
if isinstance(possible_class, (StringType, UnicodeType)): |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1725 |
possible_class = self.GetElementClass(possible_class) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1726 |
if possible_class.StructurePattern.match(children) is not None: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1727 |
return possible_class |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1728 |
return element_class[0] |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1729 |
return element_class |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1730 |
|
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1731 |
class XMLClassParser(etree.XMLParser): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1732 |
|
1330
96b242e4c59d
Added support for loading XML file even if not following XSD schema (but still following XML syntax), warning user of errors in XML file
Laurent Bessard
parents:
1322
diff
changeset
|
1733 |
def __init__(self, namespaces, default_namespace_format, base_class, xsd_schema, *args, **kwargs): |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1734 |
etree.XMLParser.__init__(self, *args, **kwargs) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1735 |
self.DefaultNamespaceFormat = default_namespace_format |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1736 |
self.NSMAP = namespaces |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1737 |
targetNamespace = etree.QName(default_namespace_format % "d").namespace |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1738 |
if targetNamespace is not None: |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1739 |
self.RootNSMAP = { |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1740 |
name if targetNamespace != uri else None: uri |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1741 |
for name, uri in namespaces.iteritems()} |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1742 |
else: |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1743 |
self.RootNSMAP = namespaces |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1744 |
self.BaseClass = base_class |
1330
96b242e4c59d
Added support for loading XML file even if not following XSD schema (but still following XML syntax), warning user of errors in XML file
Laurent Bessard
parents:
1322
diff
changeset
|
1745 |
self.XSDSchema = xsd_schema |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1746 |
|
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1747 |
def set_element_class_lookup(self, class_lookup): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1748 |
etree.XMLParser.set_element_class_lookup(self, class_lookup) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1749 |
self.ClassLookup = class_lookup |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1750 |
|
1330
96b242e4c59d
Added support for loading XML file even if not following XSD schema (but still following XML syntax), warning user of errors in XML file
Laurent Bessard
parents:
1322
diff
changeset
|
1751 |
def LoadXMLString(self, xml_string): |
96b242e4c59d
Added support for loading XML file even if not following XSD schema (but still following XML syntax), warning user of errors in XML file
Laurent Bessard
parents:
1322
diff
changeset
|
1752 |
tree = etree.fromstring(xml_string, self) |
96b242e4c59d
Added support for loading XML file even if not following XSD schema (but still following XML syntax), warning user of errors in XML file
Laurent Bessard
parents:
1322
diff
changeset
|
1753 |
if not self.XSDSchema.validate(tree): |
96b242e4c59d
Added support for loading XML file even if not following XSD schema (but still following XML syntax), warning user of errors in XML file
Laurent Bessard
parents:
1322
diff
changeset
|
1754 |
error = self.XSDSchema.error_log.last_error |
96b242e4c59d
Added support for loading XML file even if not following XSD schema (but still following XML syntax), warning user of errors in XML file
Laurent Bessard
parents:
1322
diff
changeset
|
1755 |
return tree, (error.line, error.message) |
96b242e4c59d
Added support for loading XML file even if not following XSD schema (but still following XML syntax), warning user of errors in XML file
Laurent Bessard
parents:
1322
diff
changeset
|
1756 |
return tree, None |
96b242e4c59d
Added support for loading XML file even if not following XSD schema (but still following XML syntax), warning user of errors in XML file
Laurent Bessard
parents:
1322
diff
changeset
|
1757 |
|
1304 | 1758 |
def Dumps(self, xml_obj): |
1759 |
return etree.tostring(xml_obj) |
|
1760 |
||
1761 |
def Loads(self, xml_string): |
|
1762 |
return etree.fromstring(xml_string, self) |
|
1763 |
||
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1764 |
def CreateRoot(self): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1765 |
if self.BaseClass is not None: |
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1766 |
root = self.makeelement( |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1767 |
self.DefaultNamespaceFormat % self.BaseClass[0], |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1768 |
nsmap=self.RootNSMAP) |
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
1769 |
root._init_() |
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1770 |
return root |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1771 |
return None |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1772 |
|
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1773 |
def GetElementClass(self, element_tag, parent_tag=None): |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1774 |
return self.ClassLookup.GetElementClass( |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1775 |
self.DefaultNamespaceFormat % element_tag, |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1776 |
self.DefaultNamespaceFormat % parent_tag |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1777 |
if parent_tag is not None else parent_tag, |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1778 |
None) |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1779 |
|
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1780 |
def CreateElement(self, element_tag, parent_tag=None, class_idx=None): |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1781 |
element_class = self.GetElementClass(element_tag, parent_tag) |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1782 |
if isinstance(element_class, ListType): |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1783 |
if class_idx is not None and class_idx < len(element_class): |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1784 |
new_element = element_class[class_idx]() |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1785 |
else: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1786 |
raise ValueError, "No corresponding class found!" |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1787 |
else: |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1788 |
new_element = element_class() |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1789 |
DefaultElementClass.__setattr__(new_element, "tag", self.DefaultNamespaceFormat % element_tag) |
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
1790 |
new_element._init_() |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1791 |
return new_element |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1792 |
|
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1793 |
def GenerateParser(factory, xsdstring): |
814 | 1794 |
ComputedClasses = factory.CreateClasses() |
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1795 |
|
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1796 |
if factory.FileName is not None: |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1797 |
ComputedClasses = ComputedClasses[factory.FileName] |
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1305
diff
changeset
|
1798 |
BaseClass = [(name, XSDclass) for name, XSDclass in ComputedClasses.items() if XSDclass.IsBaseClass] |
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1799 |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1800 |
parser = XMLClassParser( |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1801 |
factory.NSMAP, |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1802 |
factory.etreeNamespaceFormat, |
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1803 |
BaseClass[0] if len(BaseClass) == 1 else None, |
1330
96b242e4c59d
Added support for loading XML file even if not following XSD schema (but still following XML syntax), warning user of errors in XML file
Laurent Bessard
parents:
1322
diff
changeset
|
1804 |
etree.XMLSchema(etree.fromstring(xsdstring)), |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1805 |
strip_cdata = False, remove_blank_text=True) |
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1806 |
class_lookup = XMLElementClassLookUp(factory.ComputedClassesLookUp) |
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1807 |
parser.set_element_class_lookup(class_lookup) |
1291
42ea51d083ce
Second stage of xmlclass refactoring using lxml , project are loaded and displayed successfully
Laurent Bessard
parents:
1290
diff
changeset
|
1808 |
|
1290
13ee5f4ab612
First stage of xmlclass refactoring using lxml
Laurent Bessard
parents:
1179
diff
changeset
|
1809 |
return parser |
814 | 1810 |