123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- from lxml import etree
- import logging
- DEFAULT_NAMESPACE_KEY = 'ns'
- DEFAULT_NAMESPACE = {DEFAULT_NAMESPACE_KEY:'http://autosar.org/schema/r4.0'}
- class Arxml:
- def __init__(self, arxml_file_name: str) -> None:
- self.__file_name: str = arxml_file_name
- self.__root: etree.Element = self.get_arxml_root()
- @property
- def root(self) -> etree.Element:
- return self.__root
- def get_arxml_root(self):
- parser = etree.XMLParser(remove_blank_text=True)
- tree = etree.parse(self.__file_name, parser=parser)
- root = tree.getroot()
- return root
- '''
- XPath 通过前缀 ns:'xxxxx' 进行namespace解析
- find findall方法则是通过 {xxxxx}TAG-NAME 进行解析
- ETXpath 类似find findall方法的形式,通过{xxxx}TAG-NAME
- '''
- @staticmethod
- def get_arxml_namespace(element: etree.Element):
- ns = element.nsmap
- # add default namespace
- if None in ns:
- ns[DEFAULT_NAMESPACE_KEY] = ns[None]
- ns.pop(None)
- elif len(ns) == 0:
- ns = None
- return ns
- @staticmethod
- def get_formated_xpath_with_namespace_key(xpath_str: str, namespace_key: str = DEFAULT_NAMESPACE_KEY):
- '''
- :param xpath_str: src xpath string
- :param namespace_key: need to
- :return:
- '''
- namespace_prefix = '{}:'.format(namespace_key) if '' != namespace_key else ''
- result = xpath_str.replace('//', '**{}'.format(namespace_prefix))
- result = result.replace('/', '/{}'.format(namespace_prefix))
- result = result.replace('**', '//')
- return result
- @staticmethod
- def get_format_xpath_pattern(xpath_str, xpath_text='', xpath_rule=None, namespace_key=DEFAULT_NAMESPACE_KEY):
- '''
- :param xpath_str:
- :param xpath_text:
- :param xpath_rule:
- CONTAINS
- TEXT_EQ
- ATTR_EQ
- :param namespace_key:
- :return:
- '''
- xpath_with_ns = Arxml.get_formated_xpath_with_namespace_key(xpath_str, namespace_key)
- if xpath_rule == 'CONTAINS':
- xpath_suffix = '[contains(text(),"{}")]'.format(xpath_text)
- elif xpath_rule == 'TEXT_EQ':
- xpath_suffix = '[text()="{}"]'.format(xpath_text)
- elif (xpath_rule == 'ATTR_EQ' and isinstance(xpath_text, dict)):
- attr_name, attr_value = xpath_text.popitem()
- xpath_suffix = '[@{}={}]'.format(attr_name, attr_value)
- else:
- xpath_suffix = ''
- pass
- return xpath_with_ns + xpath_suffix
- @staticmethod
- def get_xpath_result(element, xpath_str, xpath_text='', xpath_rule=None):
- ns = Arxml.get_arxml_namespace(element)
- if ns is None:
- ns_key = ''
- else:
- ns_key = DEFAULT_NAMESPACE_KEY
- format_xpath = Arxml.get_format_xpath_pattern(xpath_str, xpath_text, xpath_rule, ns_key)
- # print(format_xpath)
- result = element.xpath(format_xpath, namespaces=ns)
- if len(result) == 0:
- result = None
- return result
- @staticmethod
- def get_all_match_element(root_element:etree.Element, xpath_str, xpath_text='', xpath_rule=None):
- result = Arxml.get_xpath_result(root_element, xpath_str, xpath_text, xpath_rule)
- return result
- @staticmethod
- def get_first_match_element(root_element:etree.Element, xpath_str, xpath_text='', xpath_rule=None):
- result = Arxml.get_all_match_element(root_element, xpath_str, xpath_text, xpath_rule)
- if result is not None:
- result = result[0]
- return result
- @staticmethod
- def get_brother_element(current_element:etree.Element, brother_tag, xpath_text='', xpath_rule=None):
- parent = current_element.getparent()
- if parent is not None:
- brother = Arxml.get_first_match_element(parent, brother_tag, xpath_text, xpath_rule)
- else:
- brother = None
- return brother
- @staticmethod
- def get_parent_element(current_element):
- return current_element.getparent()
- @staticmethod
- def get_container_text(current_element):
- if etree.iselement(current_element):
- return current_element.text
- else:
- return ''
- @staticmethod
- def xml_write_to_file(element, output_fileName):
- print(output_fileName)
- tree = etree.ElementTree(element)
- tree.write(output_fileName, pretty_print=True, xml_declaration=True, encoding='utf-8')
- logging.debug('Generate arxml file {}'.format(output_fileName))
- @staticmethod
- def creat_child_new_element(element, element_tag, text_str='', attribute_dict={}):
- new_element = etree.Element(element_tag, attribute_dict)
- if text_str != '':
- new_element.text = text_str
- element.append(new_element)
- return new_element
- @staticmethod
- def creat_brother_new_element(cur_element, element_tag, text_str='', attribute_dict={}):
- par_element = cur_element.getparent()
- if par_element is not None:
- bro_element = Arxml.creat_child_new_element(par_element, element_tag, text_str, attribute_dict)
- else:
- bro_element = None
- return bro_element
- @staticmethod
- def get_split_end_value(long_str_value):
- return long_str_value.split('/')[-1]
- @staticmethod
- def get_element_tag(element):
- tag_with_ns = element.tag
- if tag_with_ns != '':
- if '}' in tag_with_ns:
- position = tag_with_ns.find('}')
- tag = tag_with_ns[position+1:]
- else:
- tag = tag_with_ns
- else:
- tag = ''
- return tag
- if __name__ == '__main__':
- arxml = Arxml('EH32_GW04_IpduM_ecuc.arxml')
- element = Arxml.get_first_match_element(arxml.root, './/DEFINITION-REF', 'IpduMRxDirectComInvocation', 'CONTAINS')
- par_ele = Arxml.get_parent_element(element)
- Arxml.creat_child_new_element(par_ele, 'aaaa', 'texttexttext', {'class':'1234'})
- Arxml.creat_child_new_element(par_ele, 'bbbb', '', {'class': '1234'})
- Arxml.creat_child_new_element(par_ele, 'bbbb1', 'dasfadfsad')
- cccc = Arxml.creat_child_new_element(par_ele, 'cccc')
- dddd = Arxml.creat_brother_new_element(cccc, 'dddd')
- Arxml.xml_write_to_file(arxml.root, 'test.arxml')
|