def xmlSpectrumFromSmi(index, smi, sai=None, compression='zlib'):
    """ #TODO: docstring

    :param index: The zero-based, consecutive index of the spectrum in the
        SpectrumList. (mzML specification)
    :param smi: a SpectrumMetadataItem instance
    :param sai: a SpectrumArrayItem instance, if none is specified no
        binaryDataArrayList is written
    :param compression: #TODO: docstring

    :returns: #TODO: docstring
    """
    if sai is not None:
        arrayLength = [array.size for array in viewvalues(sai.arrays)]
        if len(set(arrayLength)) != 1:
            raise Exception('Unequal size for different array in sai.arrays')
        else:
            arrayLength = arrayLength[0]
    else:
        arrayLength = 0

    spectrumAttrib = {'index': str(index), 'id': smi.attributes['id'],
                      'defaultArrayLength': str(arrayLength)}

    xmlSpectrum = ETREE.Element('spectrum', **spectrumAttrib)
    maspy.xml.xmlAddParams(xmlSpectrum, smi.params)
    #Add the scanList
    if len(smi.scanList) > 0:
        xmlSpectrum.append(xmlGenScanList(smi.scanList, smi.scanListParams))
    if len(smi.precursorList) > 0:
        xmlSpectrum.append(xmlGenPrecursorList(smi.precursorList))
    if len(smi.productList) > 0:
        xmlSpectrum.append(xmlGenProductList(smi.productList))
    if sai is not None:
        xmlSpectrum.append(xmlGenBinaryDataArrayList(sai.arrayInfo,
                                                     sai.arrays,
                                                     compression=compression
                                                     ))
    return xmlSpectrum
#TODO: docstring

    :param index: The zero-based, consecutive index of the spectrum in the
        SpectrumList. (mzML specification)
    :param smi: a SpectrumMetadataItem instance
    :param sai: a SpectrumArrayItem instance, if none is specified no
        binaryDataArrayList is written
    :param compression: #TODO: docstring

    :returns: #TODO: docstring