Python Library REQ-IF
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

xml_parser.py 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. import xml.etree.ElementTree as ET
  2. KEY_DESCRIPTION = 'description'
  3. """Description (short) of an element"""
  4. KEY_DETAILED_DESCRIPTION = 'detailed_description'
  5. """Description (short) of an element"""
  6. KEY_ITEM_ID = 'id'
  7. """The human readable item id"""
  8. KEY_LAST_CHANGE = 'last_change'
  9. """Date of the last change"""
  10. KEY_SOURCE = 'source'
  11. """The source of a relation"""
  12. KEY_SPEC_DATA = 'data'
  13. """A dict holding the data definition (key is the unique id of the data definition). Note this is not the datatype, but a reference to the datatype"""
  14. KEY_START_EXECUTION_FROM_LEVEL = 'start_execution_from_level'
  15. """The level, of an spec object from where on the test should be executed"""
  16. KEY_SYSTEM_TYPE_UID = 'system_type_uid'
  17. """The unique id of the corresponding type"""
  18. KEY_SYSTEM_UID = 'system_uid'
  19. """A unique id"""
  20. KEY_TARGET = 'target'
  21. """The target of a relation"""
  22. KEY_XML_TAG = 'xml_tag'
  23. """The tag of the original xml object"""
  24. PREFIX = '{http://www.omg.org/spec/ReqIF/20110401/reqif.xsd}'
  25. TAG_CHILDREN = '%sCHILDREN' % PREFIX
  26. TAG_DEFINITION = '%sDEFINITION' % PREFIX
  27. TAG_OBJECT = '%sOBJECT' % PREFIX
  28. TAG_OBJECT_REF = '%sSPEC-OBJECT-REF' % PREFIX
  29. TAG_PROPERTIES = '%sPROPERTIES' % PREFIX
  30. TAG_SOURCE = '%sSOURCE' % PREFIX
  31. TAG_SPECIFIED_VALUES = '%sSPECIFIED-VALUES' % PREFIX
  32. TAG_SPEC_ATTRIBUTES = '%sSPEC-ATTRIBUTES' % PREFIX
  33. TAG_TARGET = '%sTARGET' % PREFIX
  34. TAG_THE_VALUE = 'THE-VALUE'
  35. TAG_TYPE = '%sTYPE' % PREFIX
  36. TAG_VALUES = '%sVALUES' % PREFIX
  37. class base_object(dict):
  38. ATTRIB_KEY_DESC = 'DESC'
  39. ATTRIB_KEY_IDENTIFIER = 'IDENTIFIER'
  40. ATTRIB_KEY_LONG_NAME = 'LONG-NAME'
  41. ATTRIB_KEY_LAST_CHANGE = 'LAST-CHANGE'
  42. ATTRIB_DATA = {KEY_DESCRIPTION: ATTRIB_KEY_LONG_NAME,
  43. KEY_DETAILED_DESCRIPTION: ATTRIB_KEY_DESC,
  44. KEY_LAST_CHANGE: ATTRIB_KEY_LAST_CHANGE,
  45. KEY_SYSTEM_UID: ATTRIB_KEY_IDENTIFIER}
  46. def __init__(self, xml_object):
  47. dict.__init__(self)
  48. for key in self.ATTRIB_DATA:
  49. data = xml_object.attrib.get(self.ATTRIB_DATA[key])
  50. if data is not None:
  51. self[key] = data
  52. self[KEY_XML_TAG] = xml_object.tag
  53. type_obj = xml_object.find(TAG_TYPE)
  54. if type_obj is not None:
  55. self[KEY_SYSTEM_TYPE_UID] = type_obj[0].text
  56. def __str__(self):
  57. keys = self.keys()
  58. keys.sort()
  59. rv = ''
  60. for key in keys:
  61. rv += '%s: %s\n' % (key, self[key])
  62. return rv
  63. class datatype(base_object):
  64. ATTRIB_KEY_KEY = 'KEY'
  65. def __init__(self, xml_datatype_object):
  66. base_object.__init__(self, xml_datatype_object)
  67. self.enmu_dict = dict()
  68. if 'ENUMERATION' in self[KEY_XML_TAG]:
  69. for child in xml_datatype_object.find(TAG_SPECIFIED_VALUES):
  70. key = child.attrib[self.ATTRIB_KEY_IDENTIFIER]
  71. value = None
  72. if child.find(TAG_PROPERTIES) is not None:
  73. try:
  74. value = int(child.find(TAG_PROPERTIES)[0].attrib.get(self.ATTRIB_KEY_KEY))
  75. except ValueError:
  76. value = child.find(TAG_PROPERTIES)[0].attrib.get(self.ATTRIB_KEY_KEY)
  77. value = value or child.attrib[self.ATTRIB_KEY_LONG_NAME]
  78. self.enmu_dict[key] = value
  79. def xml_obj_to_value(self, xml_obj):
  80. if 'STRING' in self[KEY_XML_TAG]:
  81. data = xml_obj.attrib.get(TAG_THE_VALUE)
  82. return data
  83. elif 'INTEGER' in self[KEY_XML_TAG]:
  84. data = xml_obj.attrib.get(TAG_THE_VALUE)
  85. return int(data)
  86. elif 'BOOLEAN' in self[KEY_XML_TAG]:
  87. data = xml_obj.attrib.get(TAG_THE_VALUE)
  88. if data.lower() == 'false':
  89. return False
  90. else:
  91. return True
  92. elif 'ENUMERATION' in self[KEY_XML_TAG]:
  93. if xml_obj.find(TAG_VALUES) is not None:
  94. return self.enmu_dict.get(xml_obj.find(TAG_VALUES)[0].text)
  95. class datatype_dict(dict):
  96. def __init__(self, xml_datatypes_object):
  97. dict.__init__(self)
  98. for child in xml_datatypes_object:
  99. dt = datatype(child)
  100. self[dt[KEY_SYSTEM_UID]] = dt
  101. def __str__(self):
  102. rv = ''
  103. for key in self:
  104. rv += str(self[key]) + '\n'
  105. return rv
  106. class spec_type(base_object):
  107. def __init__(self, xml_spec_type_object):
  108. base_object.__init__(self, xml_spec_type_object)
  109. self[KEY_SPEC_DATA] = dict()
  110. for child in xml_spec_type_object.find(TAG_SPEC_ATTRIBUTES):
  111. a = base_object(child)
  112. self[KEY_SPEC_DATA][a[KEY_SYSTEM_UID]] = a
  113. class spec_types_dict(dict):
  114. def __init__(self, xml_spec_types_object):
  115. dict.__init__(self)
  116. for child in xml_spec_types_object:
  117. st = spec_type(child)
  118. self[st[KEY_SYSTEM_UID]] = st
  119. def __str__(self):
  120. rv = ''
  121. for key in self:
  122. rv += str(self[key]) + '\n'
  123. return rv
  124. class spec_object(base_object):
  125. def __init__(self, xml_object, spec_types, data_types):
  126. base_object.__init__(self, xml_object)
  127. try:
  128. for child in xml_object.find(TAG_VALUES):
  129. attr_id = child.find(TAG_DEFINITION)[0].text
  130. stype = spec_types[self[KEY_SYSTEM_TYPE_UID]]
  131. if attr_id in stype[KEY_SPEC_DATA]:
  132. spec_attr = stype[KEY_SPEC_DATA][attr_id]
  133. data_type = data_types[spec_attr[KEY_SYSTEM_TYPE_UID]]
  134. self[spec_attr[KEY_DESCRIPTION]] = data_type.xml_obj_to_value(child)
  135. except TypeError:
  136. pass
  137. class spec_objects(dict):
  138. def __init__(self, xml_object, spec_types, data_types):
  139. dict.__init__(self)
  140. for child in xml_object:
  141. so = spec_object(child, spec_types, data_types)
  142. self[so[KEY_SYSTEM_UID]] = so
  143. def __str__(self):
  144. rv = ''
  145. for key in self:
  146. rv += str(self[key]) + '\n'
  147. return rv
  148. class spec_relation(spec_object):
  149. def __init__(self, xml_object, spec_types, data_types):
  150. spec_object.__init__(self, xml_object, spec_types, data_types)
  151. self[KEY_SOURCE] = xml_object.find(TAG_SOURCE).find(TAG_OBJECT_REF).text
  152. self[KEY_TARGET] = xml_object.find(TAG_TARGET).find(TAG_OBJECT_REF).text
  153. class spec_relations(list):
  154. def __init__(self, xml_object, spec_types, data_types):
  155. list.__init__(self)
  156. for child in xml_object:
  157. self.append(spec_relation(child, spec_types, data_types))
  158. def __str__(self):
  159. rv = ''
  160. for key in self:
  161. rv += str(self[key]) + '\n'
  162. return rv
  163. class id_tree(str):
  164. def __init__(self, system_uid):
  165. str.__init__(system_uid)
  166. self.children = list()
  167. def append(self, child):
  168. self.children.append(child)
  169. def get_flat_id_tree(self):
  170. """
  171. This method returns an ordered but flat list of all id_tree elements.
  172. """
  173. obj_list = list()
  174. for child in self.children:
  175. obj_list.append(child)
  176. obj_list.extend(child.get_flat_id_tree())
  177. return obj_list
  178. def executed_or_has_executed_children(self, item_type_id, execution_level, get_spec_object_method, default_execution_level):
  179. spec_obj = get_spec_object_method(str(self))
  180. if spec_obj[KEY_SYSTEM_TYPE_UID] == item_type_id:
  181. if execution_level >= spec_obj.get(KEY_START_EXECUTION_FROM_LEVEL, default_execution_level):
  182. return True
  183. for child in self.children:
  184. if child.executed_or_has_executed_children(item_type_id, execution_level, get_spec_object_method, default_execution_level):
  185. return True
  186. return False
  187. class specification(spec_object):
  188. def __init__(self, xml_object, spec_types, data_types, spec_objects):
  189. spec_object.__init__(self, xml_object, spec_types, data_types)
  190. self._spec_objects = spec_objects
  191. self.children = list()
  192. self._add_hirarchy_objects(xml_object.find(TAG_CHILDREN), self.children)
  193. def _add_hirarchy_objects(self, children, parent_list):
  194. for child in children:
  195. child_id = child.find('%s/%s' % (TAG_OBJECT, TAG_OBJECT_REF)).text
  196. child_tree_obj = id_tree(child_id)
  197. parent_list.append(child_tree_obj)
  198. next_children = child.find(TAG_CHILDREN)
  199. if next_children is not None:
  200. self._add_hirarchy_objects(next_children, child_tree_obj.children)
  201. def get_system_uid_list_by_type(self, type_id):
  202. """
  203. This method returns an ordered but flat list of all items of this specification with the specified type.
  204. """
  205. obj_list = list()
  206. for child in self.children:
  207. if self._spec_objects[child][KEY_SYSTEM_TYPE_UID] == type_id:
  208. obj_list.append(str(child))
  209. for item_id in child.get_flat_id_tree():
  210. if self._spec_objects[item_id][KEY_SYSTEM_TYPE_UID] == type_id:
  211. obj_list.append(str(item_id))
  212. return obj_list
  213. class specifications(list):
  214. def __init__(self, xml_object, spec_types, data_types, spec_objects):
  215. list.__init__(self)
  216. for child in xml_object:
  217. self.append(specification(child, spec_types, data_types, spec_objects))
  218. def __str__(self):
  219. rv = ''
  220. for i in self:
  221. rv += str(i) + '\n'
  222. return rv
  223. class parse(object):
  224. TAG_HEADER_MAIN = '%sTHE-HEADER' % PREFIX
  225. TAG_HEADER_REQIF = '%sREQ-IF-HEADER' % PREFIX
  226. TAG_TITLE = '%sTITLE' % PREFIX
  227. TAG_COMMENT = '%sCOMMENT' % PREFIX
  228. TAG_CORE_CONTENT = '%sCORE-CONTENT' % PREFIX
  229. TAG_REQ_IF_CONTENT = '%sREQ-IF-CONTENT' % PREFIX
  230. TAG_DATATYPES = '%sDATATYPES' % PREFIX
  231. TAG_SPEC_RELATIONS = '%sSPEC-RELATIONS' % PREFIX
  232. TAG_SPEC_TYPES = '%sSPEC-TYPES' % PREFIX
  233. TAG_SPEC_OBJECTS = '%sSPEC-OBJECTS' % PREFIX
  234. TAG_SPECIFICATION = '%sSPECIFICATIONS' % PREFIX
  235. def __init__(self, filename):
  236. tree = ET.parse(filename)
  237. req_if = tree.getroot()
  238. self._title = req_if.find('./%s/%s/%s' % (self.TAG_HEADER_MAIN, self.TAG_HEADER_REQIF, self.TAG_TITLE)).text
  239. self._comment = req_if.find('./%s/%s/%s' % (self.TAG_HEADER_MAIN, self.TAG_HEADER_REQIF, self.TAG_COMMENT)).text
  240. xml_obj = req_if.find('./%s/%s/%s' % (self.TAG_CORE_CONTENT, self.TAG_REQ_IF_CONTENT, self.TAG_DATATYPES))
  241. self._datatypes = datatype_dict(xml_obj)
  242. xml_obj = req_if.find('./%s/%s/%s' % (self.TAG_CORE_CONTENT, self.TAG_REQ_IF_CONTENT, self.TAG_SPEC_TYPES))
  243. self._spec_types = spec_types_dict(xml_obj)
  244. xml_obj = req_if.find('./%s/%s/%s' % (self.TAG_CORE_CONTENT, self.TAG_REQ_IF_CONTENT, self.TAG_SPEC_OBJECTS))
  245. self._spec_objects = spec_objects(xml_obj, self._spec_types, self._datatypes)
  246. xml_obj = req_if.find('./%s/%s/%s' % (self.TAG_CORE_CONTENT, self.TAG_REQ_IF_CONTENT, self.TAG_SPEC_RELATIONS))
  247. try:
  248. self._relations = spec_relations(xml_obj, self._spec_types, self._datatypes)
  249. except TypeError:
  250. self._relations = []
  251. xml_obj = req_if.find('./%s/%s/%s' % (self.TAG_CORE_CONTENT, self.TAG_REQ_IF_CONTENT, self.TAG_SPECIFICATION))
  252. self._specifications = specifications(xml_obj, self._spec_types, self._datatypes, self._spec_objects)
  253. def __str__(self):
  254. rv = 'Title: %s' % self._title
  255. rv += 'Comment: %s' % self._comment
  256. rv += 'DATATYPES:\n----------\n'
  257. rv += str(self._datatypes)
  258. rv += str(self._spec_types)
  259. rv += '\n\n\nSPEC_OBJECTS:\n-------------\n'
  260. rv += str(self._spec_objects)
  261. rv += '\n\n\nSPECIFICATIONS:\n---------------\n'
  262. rv += str(self._specifications)
  263. return rv