Arxml.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. from lxml import etree
  2. import logging
  3. DEFAULT_NAMESPACE_KEY = 'ns'
  4. DEFAULT_NAMESPACE = {DEFAULT_NAMESPACE_KEY:'http://autosar.org/schema/r4.0'}
  5. class Arxml:
  6. def __init__(self, arxml_file_name: str) -> None:
  7. self.__file_name: str = arxml_file_name
  8. self.__root: etree.Element = self.get_arxml_root()
  9. @property
  10. def root(self) -> etree.Element:
  11. return self.__root
  12. def get_arxml_root(self):
  13. parser = etree.XMLParser(remove_blank_text=True)
  14. tree = etree.parse(self.__file_name, parser=parser)
  15. root = tree.getroot()
  16. return root
  17. '''
  18. XPath 通过前缀 ns:'xxxxx' 进行namespace解析
  19. find findall方法则是通过 {xxxxx}TAG-NAME 进行解析
  20. ETXpath 类似find findall方法的形式,通过{xxxx}TAG-NAME
  21. '''
  22. @staticmethod
  23. def get_arxml_namespace(element: etree.Element):
  24. ns = element.nsmap
  25. # add default namespace
  26. if None in ns:
  27. ns[DEFAULT_NAMESPACE_KEY] = ns[None]
  28. ns.pop(None)
  29. elif len(ns) == 0:
  30. ns = None
  31. return ns
  32. @staticmethod
  33. def get_formated_xpath_with_namespace_key(xpath_str: str, namespace_key: str = DEFAULT_NAMESPACE_KEY):
  34. '''
  35. :param xpath_str: src xpath string
  36. :param namespace_key: need to
  37. :return:
  38. '''
  39. namespace_prefix = '{}:'.format(namespace_key) if '' != namespace_key else ''
  40. result = xpath_str.replace('//', '**{}'.format(namespace_prefix))
  41. result = result.replace('/', '/{}'.format(namespace_prefix))
  42. result = result.replace('**', '//')
  43. return result
  44. @staticmethod
  45. def get_format_xpath_pattern(xpath_str, xpath_text='', xpath_rule=None, namespace_key=DEFAULT_NAMESPACE_KEY):
  46. '''
  47. :param xpath_str:
  48. :param xpath_text:
  49. :param xpath_rule:
  50. CONTAINS
  51. TEXT_EQ
  52. ATTR_EQ
  53. :param namespace_key:
  54. :return:
  55. '''
  56. xpath_with_ns = Arxml.get_formated_xpath_with_namespace_key(xpath_str, namespace_key)
  57. if xpath_rule == 'CONTAINS':
  58. xpath_suffix = '[contains(text(),"{}")]'.format(xpath_text)
  59. elif xpath_rule == 'TEXT_EQ':
  60. xpath_suffix = '[text()="{}"]'.format(xpath_text)
  61. elif (xpath_rule == 'ATTR_EQ' and isinstance(xpath_text, dict)):
  62. attr_name, attr_value = xpath_text.popitem()
  63. xpath_suffix = '[@{}={}]'.format(attr_name, attr_value)
  64. else:
  65. xpath_suffix = ''
  66. pass
  67. return xpath_with_ns + xpath_suffix
  68. @staticmethod
  69. def get_xpath_result(element, xpath_str, xpath_text='', xpath_rule=None):
  70. ns = Arxml.get_arxml_namespace(element)
  71. if ns is None:
  72. ns_key = ''
  73. else:
  74. ns_key = DEFAULT_NAMESPACE_KEY
  75. format_xpath = Arxml.get_format_xpath_pattern(xpath_str, xpath_text, xpath_rule, ns_key)
  76. # print(format_xpath)
  77. result = element.xpath(format_xpath, namespaces=ns)
  78. if len(result) == 0:
  79. result = None
  80. return result
  81. @staticmethod
  82. def get_all_match_element(root_element:etree.Element, xpath_str, xpath_text='', xpath_rule=None):
  83. result = Arxml.get_xpath_result(root_element, xpath_str, xpath_text, xpath_rule)
  84. return result
  85. @staticmethod
  86. def get_first_match_element(root_element:etree.Element, xpath_str, xpath_text='', xpath_rule=None):
  87. result = Arxml.get_all_match_element(root_element, xpath_str, xpath_text, xpath_rule)
  88. if result is not None:
  89. result = result[0]
  90. return result
  91. @staticmethod
  92. def get_brother_element(current_element:etree.Element, brother_tag, xpath_text='', xpath_rule=None):
  93. parent = current_element.getparent()
  94. if parent is not None:
  95. brother = Arxml.get_first_match_element(parent, brother_tag, xpath_text, xpath_rule)
  96. else:
  97. brother = None
  98. return brother
  99. @staticmethod
  100. def get_parent_element(current_element):
  101. return current_element.getparent()
  102. @staticmethod
  103. def get_container_text(current_element):
  104. if etree.iselement(current_element):
  105. return current_element.text
  106. else:
  107. return ''
  108. @staticmethod
  109. def xml_write_to_file(element, output_fileName):
  110. print(output_fileName)
  111. tree = etree.ElementTree(element)
  112. tree.write(output_fileName, pretty_print=True, xml_declaration=True, encoding='utf-8')
  113. logging.debug('Generate arxml file {}'.format(output_fileName))
  114. @staticmethod
  115. def creat_child_new_element(element, element_tag, text_str='', attribute_dict={}):
  116. new_element = etree.Element(element_tag, attribute_dict)
  117. if text_str != '':
  118. new_element.text = text_str
  119. element.append(new_element)
  120. return new_element
  121. @staticmethod
  122. def creat_brother_new_element(cur_element, element_tag, text_str='', attribute_dict={}):
  123. par_element = cur_element.getparent()
  124. if par_element is not None:
  125. bro_element = Arxml.creat_child_new_element(par_element, element_tag, text_str, attribute_dict)
  126. else:
  127. bro_element = None
  128. return bro_element
  129. @staticmethod
  130. def get_split_end_value(long_str_value):
  131. return long_str_value.split('/')[-1]
  132. @staticmethod
  133. def get_element_tag(element):
  134. tag_with_ns = element.tag
  135. if tag_with_ns != '':
  136. if '}' in tag_with_ns:
  137. position = tag_with_ns.find('}')
  138. tag = tag_with_ns[position+1:]
  139. else:
  140. tag = tag_with_ns
  141. else:
  142. tag = ''
  143. return tag
  144. if __name__ == '__main__':
  145. arxml = Arxml('EH32_GW04_IpduM_ecuc.arxml')
  146. element = Arxml.get_first_match_element(arxml.root, './/DEFINITION-REF', 'IpduMRxDirectComInvocation', 'CONTAINS')
  147. par_ele = Arxml.get_parent_element(element)
  148. Arxml.creat_child_new_element(par_ele, 'aaaa', 'texttexttext', {'class':'1234'})
  149. Arxml.creat_child_new_element(par_ele, 'bbbb', '', {'class': '1234'})
  150. Arxml.creat_child_new_element(par_ele, 'bbbb1', 'dasfadfsad')
  151. cccc = Arxml.creat_child_new_element(par_ele, 'cccc')
  152. dddd = Arxml.creat_brother_new_element(cccc, 'dddd')
  153. Arxml.xml_write_to_file(arxml.root, 'test.arxml')