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

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