docs: def importMzml(filepath, msrunContainer=None, siAttrFromSmi=None, specfilename=None):
      """Performs a complete import of a mzml file into a maspy MsrunContainer.
  
      :paramsiAttrFromSmi: allow here to specify a custom function that extracts params a from spectrumMetadataItem
      :param specfilename: by default the filename will be used as the specfilename in the MsrunContainer and all
          mzML item instances, specify here an alternative specfilename to override the default one
      """
      #TODO: docstring
      siAttrFromSmi = defaultFetchSiAttrFromSmi if siAttrFromSmi is None else siAttrFromSmi
      if msrunContainer is None:
          msrunContainer = maspy.core.MsrunContainer()
  
      basename = os.path.basename(filepath)
      dirname = os.path.dirname(filepath)
      filename, extension = os.path.splitext(basename)
      specfilename = filename if specfilename is None else specfilename
  
      #Check if the specified file is valid for an import
      if not os.path.isfile(filepath):
          raise IOError('File does not exist: %s' % filepath)
      elif extension.lower() != '.mzml':
          raise IOError('Filetype is not "mzml": %s' % filepath)
      elif specfilename in msrunContainer.info:
          print(specfilename, 'already present in the msrunContainer, aborting import.')
          return None
  
      mzmlReader = maspy.xml.MzmlReader(filepath)
      masterContainer = {'rm': str(), 'ci': {}, 'si': {}, 'sai': {}, 'smi': {}}
      #Dictionary recording which MS2 scans follow a MS1 scan
      ms1Record = ddict(list)
  
      for xmlSpectrum in mzmlReader.parseSpectra():
          smi, binaryDataArrayList = smiFromXmlSpectrum(xmlSpectrum, specfilename)
          #Generate SpectrumItem
          si = maspy.core.Si(smi.id, smi.specfile)
          si.isValid = True
          siAttrFromSmi(smi, si)
          if si.msLevel > 1:
              si.precursorId = si.precursorId.split('scan=')[1] #TODO: change to use regex to extract from known vendor format
              ms1Record[si.precursorId].append(si.id)
          else:
              ms1Record[si.id] #Touch the ddict to add the MS1 id, if it is not already present
          #Generate SpectrumArrayItem
          sai = maspy.core.Sai(smi.id, smi.specfile)
          sai.arrays, sai.arrayInfo = maspy.xml.extractBinaries(binaryDataArrayList,
                                                                smi.attributes['defaultArrayLength'])
          #Store all items in the appropriate containers
          masterContainer['smi'][smi.id] = smi
          masterContainer['si'][smi.id] = si
          masterContainer['sai'][smi.id] = sai
  
      for siId, msnIdList in viewitems(ms1Record):
          #Ignore KeyError if the spectrum is not present in the mzML file for whatever reason
          try:
              setattr(masterContainer['si'][siId], 'msnIdList', msnIdList)
          except KeyError:
              pass
  
      for xmlChromatogram in mzmlReader.chromatogramList:
          ci = ciFromXml(xmlChromatogram, specfilename)
          masterContainer['ci'][ci.id] = ci
      masterContainer['rm'] = mzmlReader.metadataNode
  
      msrunContainer._addSpecfile(specfilename, dirname)
      msrunContainer.rmc[specfilename] = masterContainer['rm']
      msrunContainer.info[specfilename]['status']['rm'] = True
      msrunContainer.smic[specfilename] = masterContainer['smi']
      msrunContainer.info[specfilename]['status']['smi'] = True
      msrunContainer.sic[specfilename] = masterContainer['si']
      msrunContainer.info[specfilename]['status']['si'] = True
      msrunContainer.saic[specfilename] = masterContainer['sai']
      msrunContainer.info[specfilename]['status']['sai'] = True
      msrunContainer.cic[specfilename] = masterContainer['ci']
      msrunContainer.info[specfilename]['status']['ci'] = True
  
      return msrunContainer