如何通过 defusedxml 从 AWS SQS API 字节 xml 字符串响应中读取所有行,而不仅仅是第一行?

How to read all lines from AWS SQS API bytes xml string response via defusedxml, instead of just the first one?

代码:

from defusedxml import ElementTree as etree
s = b'<?xml version="1.0"?><GetQueueAttributesResponse xmlns="http://queue.amazonaws.com/doc/2012-11-05/"><GetQueueAttributesResult><Attribute><Name>ApproximateNumberOfMessages</Name><Value>2</Value></Attribute></GetQueueAttributesResult><ResponseMetadata><RequestId>xxxx</RequestId></ResponseMetadata></GetQueueAttributesResponse>'
print(etree.fromstring(s))

预期输出:
应显示完整的 xml 数据(与输入相同),以便进一步分析。

实际输出:
仅显示第一行。

<Element '{http://queue.amazonaws.com/doc/2012-11-05/}GetQueueAttributesResponse' at 0x09B50720>

这是它读取的所有数据。
因为我在这个输出上尝试了像 findall()getchildren() 这样的函数,它 returns 没有进一步的。

如何解决这个问题? 要么 如果有类似方法的替代库,请提出建议。

或者,如果有任何库可以直接将此类 xml 数据转换为 json/dict,那将非常有帮助。
但是,它应该将数据转换为可读形式,而不是像 xmltodict 这样的东西,它给出奇怪的 OrderedDicts.

注意: 建议使用哪个库也需要安全,不像 xml 那样有漏洞。

from defusedxml import ElementTree as etree
tree = etree.parse('file.xml')
root = tree.getroot()
# gives the below output
   <Element '{http://queue.amazonaws.com/doc/2012-11-05/}GetQueueAttributesResponse' at 0x1107c7b88>
root.findall('.//{http://queue.amazonaws.com/doc/2012-11-05/}Attribute')
# gives the below output
   [<Element '{http://queue.amazonaws.com/doc/2012-11-05/}Attribute' at 0x1107c7c28>]

但我不得不将 xml 另存为文件。

内联更新 xml: 与文件另存为单独文件时的工作方式相同。

s = b'<?xml version="1.0"?><GetQueueAttributesResponse xmlns="http://queue.amazonaws.com/doc/2012-11-05/"><GetQueueAttributesResult><Attribute><Name>ApproximateNumberOfMessages</Name><Value>2</Value></Attribute></GetQueueAttributesResult><ResponseMetadata><RequestId>xxxx</RequestId></ResponseMetadata></GetQueueAttributesResponse>'
etree.fromstring(s).findall('.//{http://queue.amazonaws.com/doc/2012-11-05/}Attribute')

参考:

能够根据以上示例和参考形成简洁的逻辑。

from defusedxml import ElementTree as ETree

def parse_xml(xml, tag):
    xml_tree = ETree.fromstring(xml)
    xml_tree_str = str(xml_tree)
    xpath = xml_tree_str[xml_tree_str.find("{"): xml_tree_str.find("}") + 1]
    return [
        {attr.tag[attr.tag.find("}") + 1 :]: attr.text for attr in element}
        for element in xml_tree.findall(f".//{xpath}{tag}")
    ]
from unittest import TestCase
class TestParseXML(TestCase):
    def test_parse_xml(self):
        xml = b"""<?xml version="1.0"?>
                            <XResponse xmlns="http://queue.amazonaws.com/doc/2012-11-05/">
                                <XResult>
                                    <XResultEntry>
                                        <Id>1</Id>
                                        <Name>one</Name>
                                    </XResultEntry>
                                    <XResultEntry>
                                        <Id>2</Id>
                                        <Name>two</Name>
                                    </XResultEntry>
                                </XResult>
                                <ResponseMetadata>
                                    <RequestId>testreqid</RequestId>
                                </ResponseMetadata>
                            </XResponse>"""
        data = parse_xml(xml, "XResultEntry")
        self.assertEqual(data, [{"Id": "1", "Name": "one"}, {"Id": "2", "Name": "two"}])