Read common properties from root of ReSpecTh XML file.

    Args:
        root (`~xml.etree.ElementTree.Element`): Root of ReSpecTh XML file

    Returns:
        properties (`dict`): Dictionary with common properties

def get_common_properties(root):
    """Read common properties from root of ReSpecTh XML file.

    Args:
        root (`~xml.etree.ElementTree.Element`): Root of ReSpecTh XML file

    Returns:
        properties (`dict`): Dictionary with common properties
    """
    properties = {}

    for elem in root.iterfind('commonProperties/property'):
        name = elem.attrib['name']

        if name == 'initial composition':
            properties['composition'] = {'species': [], 'kind': None}

            for child in elem.iter('component'):
                spec = {}
                spec['species-name'] = child.find('speciesLink').attrib['preferredKey']
                units = child.find('amount').attrib['units']

                # use InChI for unique species identifier (if present)
                try:
                    spec['InChI'] = child.find('speciesLink').attrib['InChI']
                except KeyError:
                    # TODO: add InChI validator/search
                    warn('Missing InChI for species ' + spec['species-name'])
                    pass

                # If mole or mass fraction, just set value
                if units in ['mole fraction', 'mass fraction', 'mole percent']:
                    spec['amount'] = [float(child.find('amount').text)]
                elif units == 'percent':
                    # assume this means mole percent
                    warn('Assuming percent in composition means mole percent')
                    spec['amount'] = [float(child.find('amount').text)]
                    units = 'mole percent'
                elif units == 'ppm':
                    # assume molar ppm, convert to mole fraction
                    warn('Assuming molar ppm in composition and converting to mole fraction')
                    spec['amount'] = [float(child.find('amount').text) * 1.e-6]
                    units = 'mole fraction'
                elif units == 'ppb':
                    # assume molar ppb, convert to mole fraction
                    warn('Assuming molar ppb in composition and converting to mole fraction')
                    spec['amount'] = [float(child.find('amount').text) * 1.e-9]
                    units = 'mole fraction'
                else:
                    raise KeywordError('Composition units need to be one of: mole fraction, '
                                       'mass fraction, mole percent, percent, ppm, or ppb.'
                                       )

                properties['composition']['species'].append(spec)

                # check consistency of composition type
                if properties['composition']['kind'] is None:
                    properties['composition']['kind'] = units
                elif properties['composition']['kind'] != units:
                    raise KeywordError('composition units ' + units +
                                       ' not consistent with ' +
                                       properties['composition']['kind']
                                       )

        elif name in datagroup_properties:
            field = name.replace(' ', '-')
            units = elem.attrib['units']
            if units == 'Torr':
                units = 'torr'
            quantity = 1.0 * unit_registry(units)
            try:
                quantity.to(property_units[field])
            except pint.DimensionalityError:
                raise KeywordError('units incompatible for property ' + name)

            properties[field] = [' '.join([elem.find('value').text, units])]

        else:
            raise KeywordError('Property ' + name + ' not supported as common property')

    return properties