transform erwin xml file, phase 0

          Posted on 2006-02-22 08:53 Under the sunshine 閱讀(481) 評論(1)  編輯  收藏
          這個東西是我的朋友Martin在處理一個老系統轉換erwin的數據庫表結構定義的xml文件到hibernate配置文件, VO和DAO時做的一個實驗,我們本來有一個牛人寫的程序來處理這些亂七八糟的表設計,可惜源代碼都丟失了,而且他的轉換是基于hibernate 1.x,有很多的先進特性無法利用,我們的目標是:
          1,erwin版本獨立,erwin這個xml文件格式隨不同的版本略有不同,希望我們的東西可以做到隔離版本帶來的問題。
          2,高效,系統中的表定義超過2000,導出的xml文件非常龐大,動輒超過三四十兆,我們希望對于表結構變動帶來的變化能夠及時響應,不能(過于)影響開發。

          初步的設想是先解析文件,得到最基本的表結構信息,主外鍵信息,然后進一步加工成我們想要得文件格式,我選擇的工具是python。
          現在準備工作已經完成了,下面是把xml文件解析成為python對象的代碼。
          下面是幾個testcase點擊下載

          import logging,logging.handlers
          logging.basicConfig(level
          =logging.DEBUG,\
                  format
          ='%(asctime)s %(levelname)s %(message)s',\
                  filename
          ='trans2.log',\
                  filemode
          ='w')
          logger 
          = logging.getLogger('trans2')

          class entity:

              
          def _parse_entity_properties(self, root):
                  entity_attrs_map 
          = _get_attributes_as_dict(root)
                  self.id 
          = entity_attrs_map['id']
                  self.name 
          = entity_attrs_map['Name']
                  
                  entity_properties_map 
          = _get_child_nodes_as_dict(root.firstChild)
                  
          if 'Physical_Name' in entity_properties_map:
                      logger.debug(
          'found Physical_Name in entity(%s)' % self.id)
                      self.physical_name 
          = entity_properties_map['Physical_Name']
                  
          else:
                      self.physical_name 
          = ''
                  logger.debug(
          'entity id = %s, name=%s, physical_name=%s'\
                          
          % (self.id, self.name,self.physical_name))

              
          def _parse_entity_attributes(self, root):
                  self.attrs 
          = []
                  attr_list 
          = root.getElementsByTagName('Attribute')
                  
          for a in attr_list:
                      attr_map 
          = {}
                      id 
          = _get_attributes_as_dict(a)['id']
                      name 
          = _get_attributes_as_dict(a)['Name']

                      child_map 
          = _get_child_nodes_as_dict(a.firstChild)
                      pysical_name 
          = ''
                      parent_attr_id 
          = ''
                      parent_relation_id 
          = ''
                      master_attr_id 
          = ''
                      nullable 
          = 1
                      
          try:
                          
          #for process some special cases
                          if 'Physical_Name' in child_map:
                              logger.debug(
          'found Physical_Name element in Attribute(%s)' % id)
                              pysical_name 
          = child_map['Physical_Name'].firstChild.data
                          
          if 'Parent_Attribute' in child_map:
                              logger.debug(
          'found Parent_Attribute element in Attribute(%s)' % id)
                              parent_attr_id 
          = child_map['Parent_Attribute'].firstChild.data 
                          
          if 'Parent_Relationship' in child_map:
                              logger.debug(
          'found Parent_Relationship element in Attribute(%s)' % id)
                              parent_relation_id 
          = child_map['Parent_Relationship'].firstChild.data 
                          
          if 'Master_Attribute' in child_map:
                              logger.debug(
          'found Master_Attribute element in Attribute(%s)' % id)
                              master_attr_id 
          = child_map['Master_Attribute'].firstChild.data 
                          
          if 'Null_Option' in child_map:
                              logger.debug(
          'found Null_Option element in Attribute(%s)' % id)
                              nullable 
          = child_map['Null_Option'].firstChild.data
                          data_type 
          = child_map['Datatype'].firstChild.data

                          attr_map 
          = {'attr_id':id,'name':name,'pysical_name':pysical_name,\
                                  
          'nullable':nullable,'data_type':data_type,'parent_attr_id':parent_attr_id\
                                  ,
          'parent_relation_id':parent_relation_id ,'master_attr_id':master_attr_id }
                      
          except KeyError,msg:
                          
          print 'warring, maybe missing some attribute\'s infomation:%s of entity %s'\
                                  % (msg, self.name)
                          logger.warn(
          'warring, maybe missing some attribute\'s infomation:%s of entity %s'\
                                  % (msg, self.name))
                  self.attrs.append(attr_map)

              
          def _parse_entity_keys(self, root):
                  self.pk 
          = {} 
                  self.fks 
          = []
                  key_list 
          = root.getElementsByTagName('Key_Group')
                  
          for k in key_list:
                      key_id 
          = _get_attributes_as_dict(k)['id'
                      key_name 
          = _get_attributes_as_dict(k)['Name']
                      
          # process Key_GroupProps, get the key type infomation 
                      key_type = _get_child_nodes_as_dict(k.firstChild)['Key_Group_Type'].firstChild.data 
                      
          # process Key_Group_MemberProps, get the key column property
                      try:
                          key_attr_id 
          =  _get_child_nodes_as_dict(k.lastChild.firstChild.firstChild)\
                                  [
          'Key_Group_Member_Column'].firstChild.data

                          key_conf 
          = {'key_id':key_id,'key_name':key_name,\
                              
          'key_type':key_type,'key_attr_id':key_attr_id}
                          
          if key_conf['key_type'== 'PK':
                              self.pk 
          = key_conf
                          
          else:
                              self.fks.append(key_conf)
                              logger.debug(
          'key_props for Key_Group(%s):%s:%s:%s'\
                                          
          % (key_id,key_name,key_type,key_attr_id))
                      
          except KeyError, msg:
                          
          print 'error, can\'t find the key defination %for %s'\
                                 % (msg, self.name)
                          logger.error(
          'error, can\'t find the key defination %for %s'\
                                 % (msg, self.name))


              
          def _reset(self):
                  self.id 
          = ''
                  self.name 
          = ''
                  self.attrs 
          = []
                  self.pk 
          = {}
                  self.fks 
          = []

              
          def __init__(self,entity_element):
                  self._reset()
                  self._parse_entity_properties(entity_element)
                  self._parse_entity_attributes(entity_element)
                  self._parse_entity_keys(entity_element)

              
          def __eq__(a,b):
                  
          return a.id == b.id

              
          def __repr__(self):
                  
          #print self.__dict__
                  return 'entity with {id:%(id)s,name:%(name)s,pk:%(pk)s' \
                          
          % self.__dict__

          class relationship:
              
          def __init__(self,relation_element):
                  self._reset()
                  self._parse_relationship(relation_element)

              
          def _reset(self):
                  self.id 
          = ''
                  self.parent_id 
          = ''
                  self.child_id 
          = ''
                  self.name 
          = ''
                  
              
          def _parse_relationship(self, relations_element):
                  attr_map 
          = _get_attributes_as_dict(relations_element)
                  self.id 
          = attr_map['id']
                  self.name 
          = attr_map['Name']
                  
                  rel_props 
          = _get_child_nodes_as_dict(relations_element.childNodes[0]) 
                  self.parent_id 
          = rel_props['Relationship_Parent_Entity'].firstChild.data
                  self.child_id 
          = rel_props['Relationship_Child_Entity'].firstChild.data
                  logger.debug(
          'parsed relation:%s:' % self)

              
          def __repr__(self):
                  
          return 'relationship with {id:%(id)s,name:%(name)s,parent_id:%(parent_id)s,child_id:%(child_id)s}' \
                          
          % self.__dict__

              
          def __eq__(a, b):
                  
          return a.id == b.id

          def _get_attributes_as_dict(element):
              attributes 
          = {}
              
          if element.attributes:
                  
          for attr in element.attributes:
                      attributes[attr.name.strip()] 
          = attr.value
              
          return attributes

          def _get_child_nodes_as_dict(element):
              child_nodes_map 
          = {}
              
          if element.childNodes:
                  
          for e in element.childNodes:
                      
          if not e.nodeType == e.TEXT_NODE:
                          child_nodes_map[e.tagName.strip()] 
          = e
                      
          else:
                          child_nodes_map[e.parentNode.tagName.strip()] 
          = e.data
              
          return child_nodes_map

          def parseXmlFile(file_name):
              
          from xml.dom.ext.reader import Sax2
              doc 
          = Sax2.FromXmlFile(file_name)
              
          return doc

          def _startParse(root):
              entities 
          = root.getElementsByTagName('Entity')
              relations 
          = root.getElementsByTagName('Relationship')
              parsed_entities 
          = [entity(item) for item in entities]
              parsed_relations 
          = [relationship(item) for item in relations]
              
          return parsed_entities,parsed_relations

          if __name__ == '__main__':
              
          import sys,time
              start 
          = time.time()
              
          print 'start@%s' % start
              root 
          = parseXmlFile(sys.argv[1])
              entities,relations 
          = _startParse(root.documentElement)
              end 
          = time.time()
              
          print 'stop@%s' % end
              
          print 'cost %s' % (end - start) 

          Feedback

          # re: transform erwin xml file, phase 0  回復  更多評論   

          2006-02-22 09:12 by Eric
          補充說明:
          忘了寫這個程序依賴的庫了:
          1, pyxml,sourceforge上的一個開源包,from python xml SIG
          2, 4suite, from http://4suite.org

          只有注冊用戶登錄后才能發表評論。


          網站導航:
          博客園   IT新聞   Chat2DB   C++博客   博問  
           

          posts - 16, comments - 3, trackbacks - 0, articles - 0

          Copyright © Under the sunshine

          主站蜘蛛池模板: 家居| 灵宝市| 乌兰浩特市| 万盛区| 九龙县| 克东县| 阜阳市| 乌拉特后旗| 砀山县| 罗田县| 永靖县| 古丈县| 宾川县| 商都县| 蓬安县| 泽库县| 景洪市| 墨玉县| 河津市| 宁晋县| 诸暨市| 临高县| 南充市| 中牟县| 剑阁县| 广丰县| 博兴县| 宝兴县| 茂名市| 虎林市| 渑池县| 呼图壁县| 双鸭山市| 博乐市| 天等县| 抚宁县| 石台县| 凤冈县| 怀柔区| 金乡县| 磴口县|