用于解析nokia设备的scfc/vendor等xml文件。用xml.etree.ElementTree来写,相比QXmlStreamReader要简洁的太多!
from collections import OrderedDict import xml.etree.ElementTree as ET import os import time import ngmainwin class NgXmlParser(object): def __init__(self, ngwin, inDir, outDir=None): self.ngwin = ngwin self.inDir = inDir if outDir is None: self.outDir = self.inDir else: self.outDir = outDir self.data = OrderedDict() def start(self): ts = time.strftime('%Y%m%d%H%M%S', time.localtime()) for root, dirs, files in os.walk(self.inDir): self.xmls = sorted([os.path.join(root, fn) for fn in files if fn.endswith('xml')], key=str.lower) self.isScfc = False self.enbId = None for fn in self.xmls: self.data.clear() self.parseXml(fn) with open(os.path.join(self.outDir, 'xml_parsed_%s.dat' % ts), 'a') as f: f.write('#%s\n' % fn) for dn in self.data.keys(): f.write('$DN=%s\n' % dn) for par, val in self.data[dn].items(): if isinstance(val, list): f.write('%s=(%s)\n' % (par, ','.join(val))) else: f.write('%s=%s\n' % (par, val)) def parseXml(self, fn): self.ngwin.logEdit.append('Parsing %s' % fn) bn = os.path.basename(fn).lower() if bn.startswith('scfc'): self.isScfc = True else: self.isScfc = False try: root = ET.parse(fn).getroot() except Exception as e: self.ngwin.logEdit.append("ERROR: fail to parse file: %s!" % fn) ''' self.ngwin.logEdit.append(root.tag, root.attrib) for child in root: self.ngwin.logEdit.append(child.tag, child.attrib) ''' #xml with namespace xmlns = '{raml21.xsd}' cm = root.find(xmlns + 'cmData') for mo in cm.findall(xmlns + 'managedObject'): dn = mo.get('distName') tokens = dn.split('/') if self.isScfc and self.enbId is None: self.enbId = tokens[0].split('-')[-1] elif self.enbId is not None: dn = dn.replace('*', self.enbId) self.data[dn] = OrderedDict() for _list in mo.findall(xmlns + 'list'): listName = _list.get('name') for item in _list.findall(xmlns + 'item'): for p in item.findall(xmlns + 'p'): par = listName + '.' + p.get('name') if par in self.data[dn]: self.data[dn][par].append(p.text) else: self.data[dn][par] = [p.text] for p in mo.findall(xmlns + 'p'): par = p.get('name') self.data[dn][par] = p.text