<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _extract_upnperror(self, err_xml):
 """ Extract the error code and error description from an error returned by the device. """

        nsmap = {'s': list(err_xml.nsmap.values())[0]}
        fault_str = err_xml.findtext(
            's:Body/s:Fault/faultstring', namespaces=nsmap)
        try:
            err = err_xml.xpath(
                's:Body/s:Fault/detail/*[name()="%s"]' % fault_str, namespaces=nsmap)[0]
        except IndexError:
            msg = 'Tag with name of %r was not found in the error response.' % fault_str
            self._log.debug(
                msg + '\n' + etree.tostring(err_xml, pretty_print=True).decode('utf8'))
            raise SOAPProtocolError(msg)

        err_code = err.findtext('errorCode', namespaces=err.nsmap)
        err_desc = err.findtext('errorDescription', namespaces=err.nsmap)

        if err_code is None or err_desc is None:
            msg = 'Tags errorCode or errorDescription were not found in the error response.'
            self._log.debug(
                msg + '\n' + etree.tostring(err_xml, pretty_print=True).decode('utf8'))
            raise SOAPProtocolError(msg)
        return int(err_code), err_desc