def parse_listdelimited_aws_xml(xml_stream, list_tags=None):
    # One fundamental assumption we make here is that elements contain text
    # xor other elements.
    if list_tags is None:
        list_tags = ()
    stack = [(None, {})]
    try:
        for event, elem in ElementTree.iterparse(xml_stream,
                                                 events=('start', 'end')):
            tag = _strip_ns(elem.tag)
            if event[0] == 's':  # start
                if tag in list_tags:
                    # Start a new list
                    stack.append((tag, []))
                else:
                    stack.append((tag, {}))
            else:  # end
                assert tag == stack[-1][0]
                if isinstance(stack[-2][1], list):
                    # Add the thing we just finished parsing to the list
                    if stack[-1][1] == {}:
                        # No inner elements; use text instead
                        if elem.text is not None:
                            stack[-2][1].append(elem.text)
                        else:
                            # No text either, so use {} to make code like this
                            # work when presented with an empty element that
                            # does not match a list tag:
                            # response.get('foo', {}).get('bar')
                            stack[-2][1].append({})
                    else:
                        stack[-2][1].append(stack[-1][1])
                else:
                    # Add the thing we just finished parsing to the dict
                    if stack[-1][1] == {}:
                        # No inner elements; use text instead
                        if elem.text is not None:
                            stack[-2][1][tag] = elem.text
                        else:
                            # No text either, so use {} to make code like this
                            # work when presented with an empty element that
                            # does not match a list tag:
                            # response.get('foo', {}).get('bar')
                            stack[-2][1][tag] = {}
                    else:
                        stack[-2][1][tag] = stack[-1][1]
                stack.pop()
                elem.clear()  # free up some memory
    except (ParseError, SyntaxError):
        raise ValueError('XML parse error')
    return stack[0][1]
Parse a stream of XML and return a nested dict.  The dict represents each
dataset/ETHPy150Open boto/requestbuilder/requestbuilder/xmlparse.py/parse_listdelimited_aws_xml