正在 Python 中解析 soap/XML 响应

Parsing soap/XML response in Python

我正在尝试使用 python 解析以下 xml。我不明白这是哪种 xml,因为我从来没有研究过这种 xml.I 只是从 api 微软的回复中得到的。

现在我的问题是如何在我的 python 代码中解析和获取 BinarySecurityToken 的值。

我参考这个问题Parse XML SOAP response with Python

但是看起来这也有一些 xmlns 来获取文本。但是在我的 xml 中我看不到任何附近的 xmlns 值,通过我可以获得值。

请告诉我如何使用 python 从下面 xml.

获取特定字段的值
<?xml version="1.0" encoding="utf-8" ?>
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsa="http://www.w3.org/2005/08/addressing">
  <S:Header>
    <wsa:Action xmlns:S="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Action" S:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue</wsa:Action>
    <wsa:To xmlns:S="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="To" S:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
    <wsse:Security S:mustUnderstand="1">
      <wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="TS">
        <wsu:Created>2017-06-12T10:23:01Z</wsu:Created>
        <wsu:Expires>2017-06-12T10:28:01Z</wsu:Expires>
      </wsu:Timestamp>
    </wsse:Security>
  </S:Header>
  <S:Body>
    <wst:RequestSecurityTokenResponse xmlns:S="http://www.w3.org/2003/05/soap-envelope" xmlns:wst="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:psf="http://schemas.microsoft.com/Passport/SoapServices/SOAPFault">
      <wst:TokenType>urn:passport:compact</wst:TokenType>
      <wsp:AppliesTo xmlns:wsa="http://www.w3.org/2005/08/addressing">
        <wsa:EndpointReference>
          <wsa:Address>https://something.something.something.com</wsa:Address>
        </wsa:EndpointReference>
      </wsp:AppliesTo>
      <wst:Lifetime>
        <wsu:Created>2017-06-12T10:23:01Z</wsu:Created>
        <wsu:Expires>2017-06-13T10:23:01Z</wsu:Expires>
      </wst:Lifetime>
      <wst:RequestedSecurityToken>
        <wsse:BinarySecurityToken Id="Compact0">my token</wsse:BinarySecurityToken>
      </wst:RequestedSecurityToken>
      <wst:RequestedAttachedReference>
        <wsse:SecurityTokenReference>
          <wsse:Reference URI="wwwww=">
          </wsse:Reference>
        </wsse:SecurityTokenReference>
      </wst:RequestedAttachedReference>
      <wst:RequestedUnattachedReference>
        <wsse:SecurityTokenReference>
          <wsse:Reference URI="swsw=">
          </wsse:Reference>
        </wsse:SecurityTokenReference>
      </wst:RequestedUnattachedReference>
    </wst:RequestSecurityTokenResponse>
  </S:Body>
</S:Envelope>

此声明是根元素开始标记的一部分:

xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"

表示wsse前缀的元素(如BinarySecurityToken)在http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd命名空间中。

解决方案与链接问题的答案基本相同。这只是另一个命名空间:

import xml.etree.ElementTree as ET

tree = ET.parse('soap.xml')    
print tree.find('.//{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}BinarySecurityToken').text

这是另一种方法:

import xml.etree.ElementTree as ET

ns = {"wsse": "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"}
tree = ET.parse('soap.xml') 
print tree.find('.//wsse:BinarySecurityToken', ns).text

两种情况下的输出都是my token

https://docs.python.org/2.7/library/xml.etree.elementtree.html#parsing-xml-with-namespaces

创建命名空间字典对我很有帮助。感谢@mzjn 链接那篇文章。

在我的 SOAP 响应中,我发现我必须使用元素的完整路径来提取文本。

例如,我正在使用 FEDEX API,我需要查找的一个元素是 TrackDetails。我最初的 .find() 看起来像 .find('{http://fedex.com/ws/track/v16}TrackDetails')

我能够将其简化为以下内容:

ns = {'TrackDetails': 'http://fedex.com/ws/track/v16'}
tree.find('TrackDetails:TrackDetails',ns)

你看到 TrackDetails 两次是因为我在字典中将键命名为 TrackDetails,但你可以随意命名。只是帮助我记住了我在我的项目中所做的工作,但是 : 之后的 TrackDetails 是我需要的 SOAP 响应中的实际元素。

希望这对某人有所帮助!