如何用Python解析SOAP XML?

svujldwt  于 2022-11-19  发布在  Python
关注(0)|答案(5)|浏览(199)

**目标:获取<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来解析soapxml,但我发现很难理解。

nnvyjq4y

nnvyjq4y1#

这里的问题是如何处理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)

命名空间分别来自EnvelopeGetStartEndPointResponse节点上的xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"xmlns="http://www.etis.fskab.se/v1.0/ETISws"属性。
请记住,父节点的所有子节点都会继承名称空间,即使子节点的标签上未明确指定名称空间为<namespace:tag>
注意:我不得不使用response.content而不是response.body

wmvff8tz

wmvff8tz2#

一个老问题,但值得一提的是,这一任务的另一个选择。
我喜欢使用xmltodict(Github)一个XML到python字典的轻量级转换器。
在名为stack的变量中获取soap响应
使用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')])]
fnvucqvd

fnvucqvd3#

再次回答一个老问题,但我认为这个解决方案值得分享。使用BeautifulSoup对我来说是小菜一碟。你可以从here安装BeautifulSoup。

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
sigwle7e

sigwle7e4#

只需将所有'soap:'和其他命名空间前缀(如'a:')替换为''(只需删除它们并使其成为非SOAP xml文件)
new_response = response.text.replace('soap:', '').replace('a:', '')
然后你就可以正常进行了。

6psbrbz9

6psbrbz95#

这样试试

import requests
from bs4 import BeautifulSoup
    
response = requests.get('http://www.labs.skanetrafiken.se/v2.2/querystation.asp?inpPointfr=yst')
    
xml = BeautifulSoup(response.text, 'xml')
xml.find('soap:Body')  # to get the soup:Body tag.
xml.find('X')  # for X tag

相关问题