代码之家  ›  专栏  ›  技术社区  ›  Clone

如何用Python解析SOAP XML?

  •  11
  • Clone  · 技术社区  · 7 年前

    获取内部值 <Name> 下面是简化的XML。

    <?xml version="1.0" encoding="UTF-8"?>
    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <soap:Body>
          <GetStartEndPointResponse xmlns="http://www.etis.fskab.se/v1.0/ETISws">
             <GetStartEndPointResult>
                <Code>0</Code>
                <Message />
                <StartPoints>
                   <Point>
                      <Id>545</Id>
                      <Name>Get Me</Name>
                      <Type>sometype</Type>
                      <X>333</X>
                      <Y>222</Y>
                   </Point>
                   <Point>
                      <Id>634</Id>
                      <Name>Get me too</Name>
                      <Type>sometype</Type>
                      <X>555</X>
                      <Y>777</Y>
                   </Point>
                </StartPoints>
             </GetStartEndPointResult>
          </GetStartEndPointResponse>
       </soap:Body>
    </soap:Envelope>
    

    import requests
    from xml.etree import ElementTree
    
    response = requests.get('http://www.labs.skanetrafiken.se/v2.2/querystation.asp?inpPointfr=yst')
    
    # XML parsing here
    dom = ElementTree.fromstring(response.text)
    names = dom.findall('*/Name')
    for name in names:
        print(name.text)
    

    我看过其他人推荐 zeep 解析soap xml,但我发现很难理解。

    4 回复  |  直到 7 年前
        1
  •  24
  •   Daniel Corin    5 年前

    这里的问题是处理XML命名空间:

    import requests
    from xml.etree import ElementTree
    
    response = requests.get('http://www.labs.skanetrafiken.se/v2.2/querystation.asp?inpPointfr=yst')
    
    # define namespace mappings to use as shorthand below
    namespaces = {
        'soap': 'http://schemas.xmlsoap.org/soap/envelope/',
        'a': 'http://www.etis.fskab.se/v1.0/ETISws',
    }
    dom = ElementTree.fromstring(response.content)
    
    # reference the namespace mappings here by `<name>:`
    names = dom.findall(
        './soap:Body'
        '/a:GetStartEndPointResponse'
        '/a:GetStartEndPointResult'
        '/a:StartPoints'
        '/a:Point'
        '/a:Name',
        namespaces,
    )
    for name in names:
        print(name.text)
    

    名称空间来自 xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://www.etis.fskab.se/v1.0/ETISws" 上的属性 Envelope GetStartEndPointResponse 节点。

    请记住,名称空间由父节点的所有子节点继承,即使名称空间没有在子标记上显式指定为 <namespace:tag> .

    response.content response.body .

        2
  •  9
  •   Grayson Briggs Samir Sadek    6 年前

    xmltodict (Github) 重量轻的 XML

    在名为的变量中获取soap响应 stack

    xmltodict.parse

    In [48]: stack_d = xmltodict.parse(stack)
    

    检查结果:

    In [49]: stack_d
    Out[49]:
    OrderedDict([('soap:Envelope',
                OrderedDict([('@xmlns:soap',
                                'http://schemas.xmlsoap.org/soap/envelope/'),
                            ('@xmlns:xsd', 'http://www.w3.org/2001/XMLSchema'),
                            ('@xmlns:xsi',
                                'http://www.w3.org/2001/XMLSchema-instance'),
                            ('soap:Body',
                                OrderedDict([('GetStartEndPointResponse',
                                            OrderedDict([('@xmlns',
                                                            'http://www.etis.fskab.se/v1.0/ETISws'),
                                                        ('GetStartEndPointResult',
                                                            OrderedDict([('Code',
                                                                        '0'),
                                                                        ('Message',
                                                                        None),
                                                                        ('StartPoints',
                                                                        OrderedDict([('Point',
                                                                                        [OrderedDict([('Id',
                                                                                                    '545'),
                                                                                                    ('Name',
                                                                                                    'Get Me'),
                                                                                                    ('Type',
                                                                                                    'sometype'),
                                                                                                    ('X',
                                                                                                    '333'),
                                                                                                    ('Y',
                                                                                                    '222')]),
                                                                                        OrderedDict([('Id',
                                                                                                    '634'),
                                                                                                    ('Name',
                                                                                                    'Get me too'),
                                                                                                    ('Type',
                                                                                                    'sometype'),
                                                                                                    ('X',
                                                                                                    '555'),
                                                                                                    ('Y',
                                                                                                    '777')])])]))]))]))]))]))])
    

    在这一点上,浏览python词汇表变得非常简单

    In [50]: stack_d['soap:Envelope']['soap:Body']['GetStartEndPointResponse']['GetStartEndPointResult']['StartPoints']['Point']
    Out[50]:
    [OrderedDict([('Id', '545'),
                ('Name', 'Get Me'),
                ('Type', 'sometype'),
                ('X', '333'),
                ('Y', '222')]),
    OrderedDict([('Id', '634'),
                ('Name', 'Get me too'),
                ('Type', 'sometype'),
                ('X', '555'),
                ('Y', '777')])]
    
        3
  •  2
  •   Rahul Rajput    4 年前

    使用BeautifulSoup对我来说是小菜一碟。你可以安装BeautifulSoup表单 here

    from bs4 import BeautifulSoup
    xml = BeautifulSoup(xml_string, 'xml')
    xml.find('soap:Body') # to get the soup:Body tag. 
    xml.find('X') # for X tag
    
        4
  •  0
  •   ZekeC    2 年前

    只需将所有“soap:”和其他名称空间前缀(如“a:”)替换为“”(只需将其删除,使其成为非soap xml文件)

    new_response = response.text.replace('soap:', '').replace('a:', '')

    然后你就可以正常进行了。