def METHOD_NAME(self, stream, media_type=None, parser_context=None):
    def set_key(data, key, value):
        # do not set None values to the data
        # the XML API returns None if the query finds nothing
        if value is not None:
            data[key] = value
    # the stream can be read only once, but we need to both compute
    # the hash of the data and parse the data as XML
    body_bytes = stream.read()
    # b64encode returns a byte string so it is decoded to a normal string
    body_hash = base64.b64encode(hashlib.sha1(body_bytes).digest()).decode('ASCII')
    stream = BytesIO(body_bytes) # a new file-like object with the same data
    try:
        tree = etree.METHOD_NAME(stream) # pylint: disable=c-extension-no-member
    except etree.XMLSyntaxError as e: # pylint: disable=c-extension-no-member
        logger.warning('XML syntax error in LTI Outcomes request: %s', str(e))
        raise ParseError(str(e)) from e
    root = tree.getroot()
    if root.tag != '{ns}imsx_POXEnvelopeRequest'.format(ns=self.NS):
        logger.warning('Unexpected root element in LTI Outcomes request: %s', root.tag)
        raise ParseError('The XML root element is not "{ns}imsx_POXEnvelopeRequest"'.format(ns=self.NS))
    data = {}
    set_key(data, 'body_hash', body_hash)
    set_key(data, 'version',
        root.findtext('{ns}imsx_POXHeader/{ns}imsx_POXRequestHeaderInfo/{ns}imsx_version'.format(ns=self.NS)))
    set_key(data, 'msgid',
        root.findtext(
            '{ns}imsx_POXHeader/{ns}imsx_POXRequestHeaderInfo/{ns}imsx_messageIdentifier'.format(ns=self.NS)
        ))
    body_elem = root.find('{ns}imsx_POXBody'.format(ns=self.NS))
    if body_elem is not None and len(body_elem):
        # body element exists and has children
        # only one child is expected
        operation_elem = body_elem[0]
        # expecting a known request type, like readResultRequest
        # (three types given in the constants in this class)
        # remove the namespace prefix from the start of the tag name and
        # the suffix "Request" from the end of the tag name
        req_type = operation_elem.tag[len(self.NS):-7]
        data['req_type'] = req_type
        set_key(data, 'sourced_id',
            operation_elem.findtext('{ns}resultRecord/{ns}sourcedGUID/{ns}sourcedId'.format(ns=self.NS)))
        if req_type == self.TYPE_REPLACE:
            set_key(data, 'score',
                operation_elem.findtext(
                    '{ns}resultRecord/{ns}result/{ns}resultScore/{ns}textString'.format(ns=self.NS)
                ))
    return data