Add signals from xml to the Frame.

def get_signals(signal_array, frame, root_or_cache, ns, multiplex_id, float_factory):
    # type: (typing.Sequence[_Element], canmatrix.Frame, _DocRoot, str, _MultiplexId, typing.Callable) -> None
    """Add signals from xml to the Frame."""
    global signal_rxs
    group_id = 1
    if signal_array is None:  # Empty signalarray - nothing to do
        return
    for signal in signal_array:
        compu_method = None
        motorola = get_child(signal, "PACKING-BYTE-ORDER", root_or_cache, ns)
        start_bit = get_child(signal, "START-POSITION", root_or_cache, ns)

        isignal = get_child(signal, "SIGNAL", root_or_cache, ns)
        if isignal is None:
            isignal = get_child(signal, "I-SIGNAL", root_or_cache, ns)
        if isignal is None:
            isignal = get_child(signal, "I-SIGNAL-GROUP", root_or_cache, ns)
            if isignal is not None:
                logger.debug("get_signals: found I-SIGNAL-GROUP ")

                isignal_array = find_children_by_path(isignal, "I-SIGNAL", root_or_cache, ns)
                get_sys_signals(isignal, isignal_array, frame, group_id, ns)
                group_id = group_id + 1
                continue
        if isignal is None:
            logger.debug(
                'Frame %s, no isignal for %s found',
                frame.name, get_child(signal, "SHORT-NAME", root_or_cache, ns).text)

        base_type = get_child(isignal, "BASE-TYPE", root_or_cache, ns)
        signal_name = None  # type: typing.Optional[str]
        signal_name_elem = get_child(isignal, "LONG-NAME", root_or_cache, ns)
        if signal_name_elem is not None:
            signal_name_elem = get_child(signal_name_elem, "L-4", root_or_cache, ns)
            if signal_name_elem is not None:
                signal_name = signal_name_elem.text
        system_signal = get_child(isignal, "SYSTEM-SIGNAL", root_or_cache, ns)
        if system_signal is None:
            logger.debug('Frame %s, signal %s has no system-signal', frame.name, isignal.tag)

        if "SYSTEM-SIGNAL-GROUP" in system_signal.tag:
            system_signals = find_children_by_path(system_signal, "SYSTEM-SIGNAL-REFS/SYSTEM-SIGNAL", root_or_cache, ns)
            get_sys_signals(system_signal, system_signals, frame, group_id, ns)
            group_id = group_id + 1
            continue

        length = get_child(isignal, "LENGTH", root_or_cache, ns)
        if length is None:
            length = get_child(system_signal, "LENGTH", root_or_cache, ns)

        name = get_child(system_signal, "SHORT-NAME", root_or_cache, ns)
        unit_element = get_child(isignal, "UNIT", root_or_cache, ns)
        display_name = get_child(unit_element, "DISPLAY-NAME", root_or_cache, ns)
        if display_name is not None:
            signal_unit = display_name.text
        else:
            signal_unit = ""

        signal_min = None  # type: canmatrix.types.OptionalPhysicalValue
        signal_max = None  # type: canmatrix.types.OptionalPhysicalValue
        receiver = []  # type: typing.List[str]

        signal_description = get_element_desc(system_signal, root_or_cache, ns)

        datatype = get_child(system_signal, "DATA-TYPE", root_or_cache, ns)
        if datatype is None:  # AR4?
            data_constr = None
            compu_method = None
            base_type = None
            for test_signal in [isignal, system_signal]:
                if data_constr is None:
                    data_constr = get_child(test_signal, "DATA-CONSTR", root_or_cache, ns)
                if compu_method is None:
                    compu_method = get_child(test_signal, "COMPU-METHOD", root_or_cache, ns)
                if base_type is None:
                    base_type = get_child(test_signal, "BASE-TYPE", root_or_cache, ns)



            lower = get_child(data_constr, "LOWER-LIMIT", root_or_cache, ns)
            upper = get_child(data_constr, "UPPER-LIMIT", root_or_cache, ns)
            encoding = None  # TODO - find encoding in AR4
        else:
            lower = get_child(datatype, "LOWER-LIMIT", root_or_cache, ns)
            upper = get_child(datatype, "UPPER-LIMIT", root_or_cache, ns)
            encoding = get_child(datatype, "ENCODING", root_or_cache, ns)

        if encoding is not None and (encoding.text == "SINGLE" or encoding.text == "DOUBLE"):
            is_float = True
        else:
            is_float = False
        
        if lower is not None and upper is not None:
            signal_min = float_factory(lower.text)
            signal_max = float_factory(upper.text)

        datdefprops = get_child(datatype, "SW-DATA-DEF-PROPS", root_or_cache, ns)

        if compu_method is None:
            compu_method = get_child(datdefprops, "COMPU-METHOD", root_or_cache, ns)
        if compu_method is None:  # AR4
            compu_method = get_child(isignal, "COMPU-METHOD", root_or_cache, ns)
            base_type = get_child(isignal, "BASE-TYPE", root_or_cache, ns)
            encoding = get_child(base_type, "BASE-TYPE-ENCODING", root_or_cache, ns)
            if encoding is not None and encoding.text == "IEEE754":
                is_float = True
        if compu_method is None:
            logger.debug('No Compmethod found!! - try alternate scheme 1.')
            networkrep = get_child(isignal, "NETWORK-REPRESENTATION-PROPS", root_or_cache, ns)
            data_def_props_var = get_child(networkrep, "SW-DATA-DEF-PROPS-VARIANTS", root_or_cache, ns)
            data_def_props_cond = get_child(data_def_props_var, "SW-DATA-DEF-PROPS-CONDITIONAL", root_or_cache, ns)
            if data_def_props_cond is not None:
                try:
                    compu_method = get_child(data_def_props_cond, "COMPU-METHOD", root_or_cache, ns)
                except:
                    logger.debug('No valid compu method found for this - check ARXML file!!')
                    compu_method = None
        #####################################################################################################
        # no found compu-method fuzzy search in systemsignal:
        #####################################################################################################
        if compu_method is None:
            logger.debug('No Compmethod found!! - fuzzy search in syssignal.')
            compu_method = get_child(system_signal, "COMPU-METHOD", root_or_cache, ns)

        # decode compuMethod:
        (values, factor, offset, unit_elem, const) = decode_compu_method(compu_method, root_or_cache, ns, float_factory)

        if signal_min is not None:
            signal_min *= factor
            signal_min += offset
        if signal_max is not None:
            signal_max *= factor
            signal_max += offset

        if base_type is None:
            base_type = get_child(datdefprops, "BASE-TYPE", root_or_cache, ns)
        if base_type is not None:
            type_name = get_element_name(base_type, ns)
            if type_name[0] == 'u':
                is_signed = False  # unsigned
            else:
                is_signed = True  # signed
        else:
            is_signed = True  # signed

        if unit_elem is not None:
            longname = get_child(unit_elem, "LONG-NAME", root_or_cache, ns)
        #####################################################################################################
        # Modification to support obtaining the Signals Unit by DISPLAY-NAME. 07June16
        #####################################################################################################
            display_name = None
            try:
                display_name = get_child(unit_elem, "DISPLAY-NAME", root_or_cache, ns)
            except:
                logger.debug('No Unit Display name found!! - using long name')
            if display_name is not None:
                signal_unit = display_name.text
            else:
                l4 = get_child(longname, "L-4", root_or_cache, ns)
                if l4 is not None:
                    signal_unit = l4.text

        init_list = find_children_by_path(system_signal, "INIT-VALUE/VALUE", root_or_cache, ns)

        if not init_list:
            init_list = find_children_by_path(isignal, "INIT-VALUE/NUMERICAL-VALUE-SPECIFICATION/VALUE", root_or_cache, ns)  # #AR4.2
        if init_list:
            initvalue = init_list[0]
        else:
            initvalue = None

        is_little_endian = False
        if motorola is not None:
            if motorola.text == 'MOST-SIGNIFICANT-BYTE-LAST':
                is_little_endian = True
        else:
            logger.debug('no name byte order for signal' + name.text)

        if name is None:
            logger.debug('no name for signal given')
        if start_bit is None:
            logger.debug('no startBit for signal given')
        if length is None:
            logger.debug('no length for signal given')

        if start_bit is not None:
            new_signal = canmatrix.Signal(
                name.text,
                start_bit=int(start_bit.text),
                size=int(length.text),
                is_little_endian=is_little_endian,
                is_signed=is_signed,
                factor=factor,
                offset=offset,
                unit=signal_unit,
                receivers=receiver,
                multiplex=multiplex_id,
                comment=signal_description,
                is_float=is_float)

            if signal_min is not None:
                new_signal.min = signal_min
            if signal_max is not None:
                new_signal.max = signal_max

            if new_signal.is_little_endian == 0:
                # startbit of motorola coded signals are MSB in arxml
                new_signal.set_startbit(int(start_bit.text), bitNumbering=1)

            # save signal, to determin receiver-ECUs for this signal later
            signal_rxs[system_signal] = new_signal

            if base_type is not None:
                temp = get_child(base_type, "SHORT-NAME", root_or_cache, ns)
                if temp is not None and "boolean" == temp.text:
                    new_signal.add_values(1, "TRUE")
                    new_signal.add_values(0, "FALSE")

            if initvalue is not None and initvalue.text is not None:
                initvalue.text = canmatrix.utils.guess_value(initvalue.text)
                new_signal._initValue = float_factory(initvalue.text)
                new_signal.add_attribute("GenSigStartValue", str(new_signal._initValue))
            else:
                new_signal._initValue = 0

            for key, value in list(values.items()):
                new_signal.add_values(key, value)
            if signal_name is not None:
                new_signal.add_attribute("LongName", signal_name)
            frame.add_signal(new_signal)