python菜鸟升级路--⾃动化解析⽣成xml⽂件
以前写过⼀个⾃动解析并⽣成netconf xml的python脚本,从性能、易读性、模块化等⼏个⽅便重构。
这个脚本的作⽤是⽣成netconf xml格式的配置⽂件。
这个脚本完成的⼯作主要有:
1. 根据表名和操作类别,就能⾃动判别或设置表ID。这⼀点⾮常重要,因为同⼀个表的不同配置页是通过ID来识别的。
2. 根据表名⾃动获取其层次关系,以及⼊参重构netconf xml配置⽂件
解决步骤详细分解如下:
1. 从l⽂档中解析出参数的层次关系
2. 解析⼊参变量,包括需要配置的表名,表⾥的参数名、参数值,以及对这个表的操作类别
3. 由于历史原因,⼊参只提供表名和操作类别,根据操作类别,设置表ID。
4. 根据2中的表名以及1中的层次关系,可以得到新xml⾥的最外层关系节点
5. 根据2中的表名以及参数,可以得到新xml⾥的最⾥层关系节点
6. 构建xml头部的hello rpc部分
7. 构建xml尾部close rpc部分
8. 将4+5+6+7组合起来构成⼀个完整的xml
现在逐条详细解析每个步骤的实现⽅案以及⽤的模块:
python处理xml文件
1. 采⽤了ElementTree模块解析l,由于l⽐较⼤有好⼏M,采⽤模块中的迭代器iter可以节省内存
的消耗。分析得到配置⽂件是树形结构,复杂交错的关系可以分为2种⽗亲映射到孩⼦,孩⼦映射到⽗亲。由于⽗亲到孩⼦是⼀对多的关系,孩⼦到⽗亲是⼀对⼀的关系。采⽤collections模块中的defaultdict(list)的数据类型来保存恰到好处。将键值是⽗亲,⽽多个孩⼦保存在列表中。配置⽂件⾥的孩⼦到⽗亲是⼀对⼀的关系,所以就⽤字典来保存。
2. 解析⼊参第⼀个想到的就是argparse模块,只是我项⽬中的⼊参是⾮标准版的,还需要适配⼀下才能⽤这个模块
3. 表ID是识别同⼀个表类⾥不同表的唯⼀标识,对于不同的操作类型,其意义还不⼀样。当操作类型是create时,表ID要与已有表ID不
同;当merge的时候,要根据表⾥的关键参数匹配当前所有配置出最相似的那条记录,然后⽐较其他的参数值,并更改之;当delete的时候,与merge类似出最相似的那张表并删除之。简化为,当create的时候,出已有表ID的最⼤值,merge或delete的时候根据匹配原则选最相似的。所以⽤collections模块⾥的counter数据结构保存表ID,跟踪表ID出现的次数,就可以很容易的得到最⼤值。对于delete或merge,采⽤zip()函数可以同时⽐较好⼏条记录与当前记录的相似度,快速⾼效。
4. 采⽤ElementTree中的Element和SubElement来构造根节点和⼦节点,同时⽤set设置attribute,⽤text设置text。构造统⼀函数构
建所有的节点。
5. 采⽤装饰器语法,将树的内容封装好,不同的操作类型对树的影响不⼀样。简单易扩展,避免写很多重复的代码。
代码如下:
步骤1对应的代码:
tree = ET.parse('l')
root = t()
allnodes = defaultdict(list)
parents = dict()
children = defaultdict(list)
for subclass in root.iter('class'):
for elem in subclass.iter('attribute'):
('name')].('name'))      for containment in root.iter('containment'):
parent = containment.find('./parent/hasClass').get('name')
child = containment.find('./child/hasClass').get('name')
parents[child] = parent
children[parent].append(child)
return allnodes,parents,children
步骤⼆对应的代码:
def BuildMoTree(Moname, params, oper):
root = ET.Element(Moname)
root.set('operation',oper)
for (key,value) in params:
onepara = ET.SubElement(root,key)
< = value
return root
步骤三:
def BuildMEMF(moname):
allnodes,parents,children = GetAllNodes()
moparent =  GetRelationships(parents, moname)
root = ET.Element('ManagedElement')
root.set('xmlns',"urn:com:ericsson:ecim:ComTop")
moparent.pop()
tmpnode = root
for parent in moparent[::-1]:
node = ET.SubElement(tmpnode,parent)
subnode = ET.SubElement(node,allnodes[parent][0])
< = '1'
if parent == 'ManagedFunction':
node.set('xmlns',"urn:com:ericsson:ecim:ManagedFunction")        tmpnode = node
return root,node
步骤四:
hello_head = ET.Element('hello')
hello_head.set('xmlns',"urn:ietf:params:xml:ns:netconf:base:1.0")    caps = ET.SubElement(hello_head,'capabilities')
cap = ET.SubElement(caps,'capability')
< = 'urn:ietf:params:netconf:base:1.0'
return hello_head
def rpc_close():
rpc_close = ET.Element('rpc')
rpc_close.set('message-id',"66")
rpc_close.set('xmlns',"urn:ietf:params:xml:ns:netconf:base:1.0")    ET.SubElement(rpc_close,'close-session')
return rpc_close
未完待续

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。