【问题标题】:Using lxml to parse xml with multiple namespaces使用 lxml 解析具有多个命名空间的 xml
【发布时间】:2015-07-22 21:19:17
【问题描述】:

我正在从 SOAP api 中提取 xml,如下所示:

<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ae="urn:sbmappservices72" xmlns:c14n="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:diag="urn:SerenaDiagnostics" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" 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:xenc="http://www.w3.org/2001/04/xmlenc#" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
    <ae:GetItemsByQueryResponse>
      <ae:return>
        <ae:item>
          <ae:id xsi:type="ae:ItemIdentifier">
            <ae:displayName/>
            <ae:id>10</ae:id>
            <ae:uuid>a9b91034-8f4d-4043-b9b6-517ba4ed3a33</ae:uuid>
            <ae:tableId>1541</ae:tableId>
            <ae:tableIdItemId>1541:10</ae:tableIdItemId>
            <ae:issueId/>
          </ae:id>

我这辈子都不能使用 findall 来拉取 tableId 之类的东西。大多数关于使用 lxml 进行解析的教程不包含命名空间,但 the one at lxml.de 包含,我一直在努力遵循它。

根据他们的教程,您应该创建一个命名空间字典,我已经这样做了:

r = tree.xpath('/e:SOAP-ENV/s:ae', 
        namespaces={'e': 'http://schemas.xmlsoap.org/soap/envelope/',
                    's': 'urn:sbmappservices72'})

但这似乎不起作用,因为当我尝试获取 r 的 len 时,它返回为 0:

print 'length: ' + str(len(r)) #<---- always equals 0

由于第二个命名空间的 URI 是“urn:”,我也尝试使用 wsdl 的真实 URL,但结果相同。

我有什么明显的遗漏吗?我只需要能够提取类似于 tableIdItemId 的值。

任何帮助将不胜感激。

【问题讨论】:

  • 其中一个命名空间是使用 URN 定义的这一事实并不重要。它与 URL 一样有效。
  • 谢谢,我是这么认为的,但由于它不起作用,我不确定。如果可以的话,我会给你一个赞成票:]

标签: python xpath soap lxml


【解决方案1】:

您的 XPath 与 XML 结构不正确对应。试试这种方式:

r = tree.xpath('/e:Envelope/e:Body/s:GetItemsByQueryResponse/s:return/s:item/s:id/s:tableId', 
        namespaces={'e': 'http://schemas.xmlsoap.org/soap/envelope/',
                    's': 'urn:sbmappservices72'})

对于小型 XML,您可能希望使用 // 而不是 / 来简化表达式,例如:

r = tree.xpath('/e:Envelope/e:Body//s:tableId', 
        namespaces={'e': 'http://schemas.xmlsoap.org/soap/envelope/',
                    's': 'urn:sbmappservices72'})

/e:Body//s:tableId 将找到tableId,无论它嵌套在Body 中的深度如何。但请注意,// 肯定比 / 慢,尤其是在应用大型 XML 时。

【讨论】:

    猜你喜欢
    • 2019-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-14
    • 2012-08-15
    • 2021-11-23
    • 2011-01-30
    • 1970-01-01
    相关资源
    最近更新 更多