【问题标题】:How should I parse this xml string in python?我应该如何在 python 中解析这个 xml 字符串?
【发布时间】:2013-01-04 09:00:08
【问题描述】:

我的 XML 字符串是 -

xmlData = """<SMSResponse xmlns="http://example.com" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
             <Cancelled>false</Cancelled>
             <MessageID>00000000-0000-0000-0000-000000000000</MessageID>  
             <Queued>false</Queued>
             <SMSError>NoError</SMSError>
             <SMSIncomingMessages i:nil="true"/>
             <Sent>false</Sent>
             <SentDateTime>0001-01-01T00:00:00</SentDateTime>
             </SMSResponse>"""

我正在尝试解析和获取标签的值 - Cancelled、MessageId、SMSError 等。我正在使用 python 的 Elementtree 库。到目前为止,我已经尝试过 -

root = ET.fromstring(xmlData)
print root.find('Sent')  // gives None
for child in root:
    print chil.find('MessageId') // also gives None

虽然,我可以使用 - 打印标签

for child in root:
    print child.tag
    //child.tag for the tag Cancelled is - {http://example.com}Cancelled

以及它们各自的值与 -

for child in root:
    print child.text

我如何得到类似 -

print child.Queued // will print false

就像在 PHP 中一样,我们可以使用 root 访问它们 -

$xml = simplexml_load_string($data);
$status = $xml->SMSError;

【问题讨论】:

    标签: python xml elementtree


    【解决方案1】:

    您的文档上有命名空间,搜索时需要包含命名空间:

    root = ET.fromstring(xmlData)
    print root.find('{http://example.com}Sent',)
    print root.find('{http://example.com}MessageID')
    

    输出:

    <Element '{http://example.com}Sent' at 0x1043e0690>
    <Element '{http://example.com}MessageID' at 0x1043e0350>
    

    find()findall() 方法也采用命名空间映射;您可以搜索任意前缀,该前缀将在该地图中查找,以节省输入:

    nsmap = {'n': 'http://example.com'}
    print root.find('n:Sent', namespaces=nsmap)
    print root.find('n:MessageID', namespaces=nsmap)
    

    【讨论】:

    • 所以基本上每次我想访问标签的文本时我都必须指定“{example.com}”?
    • @HussainTamboli:findfindall 也有一个 namespaces=mapping 参数,但是当有默认命名空间时,这似乎没用。 lxml 能更好地处理这一切。
    • 见@eclair 的回答。我想你也想这样做。 +1
    • 它仍然使用 nsmap 打印None。我认为 nsmap 有问题。
    • @HussainTamboli:我得到了您的示例 XML 的输出。确保标签名称拼写正确(MessageID 而不是 MessageId)。
    【解决方案2】:

    如果您使用 Python 标准 XML 库,则可以使用以下内容:

    root = ET.fromstring(xmlData)
    namespace = 'http://example.com'
    
    def query(tree, nodename):
        return tree.find('{{{ex}}}{nodename}'.format(ex=namespace, nodename=nodename))
    
    queued = query(root, 'Queued')
    print queued.text
    

    【讨论】:

      【解决方案3】:

      您可以创建一个字典并直接从中获取值...

      tree = ET.fromstring(xmlData)
      
      root = {}
      
      for child in tree:
          root[child.tag.split("}")[1]] = child.text
      
      print root["Queued"]
      

      【讨论】:

      • 嗨,请参阅我的编辑。 "//child.tag for the tag Cancelled is - {example.com}Cancelled" 因此很难将其与 "Cancelled" 匹配。有没有更好的办法?
      • 嘿。它有效,但这只是一个调整。如何以标签为键,文本为值的方式访问标签的文本。
      • 您也可能想将return null 更改为return Nonereturn ''。因为null,它说 - NameError: global name 'null' is not defined
      • 这也可能是另一种解决方案。 +1
      • 用一个更整洁的答案更新了答案。
      【解决方案4】:

      lxml.etree:

      In [8]: import lxml.etree as et
      
      In [9]: doc=et.fromstring(xmlData)
      
      In [10]: ns={'n':'http://example.com'}
      
      In [11]: doc.xpath('n:Queued/text()',namespaces=ns)
      Out[11]: ['false']
      

      使用elementtree,您可以:

      import xml.etree.ElementTree as ET    
      root=ET.fromstring(xmlData)    
      ns={'n':'http://example.com'}
      root.find('n:Queued',namespaces=ns).text
      Out[13]: 'false'
      

      【讨论】:

      • 谢谢。我想在 ElementTree 中找到类似的东西。 +1
      猜你喜欢
      • 1970-01-01
      • 2013-02-02
      • 1970-01-01
      • 2013-06-06
      • 1970-01-01
      • 2014-07-11
      • 2023-04-08
      • 2018-05-24
      • 1970-01-01
      相关资源
      最近更新 更多