如何使用 python 将 soap 响应中具有多个命名空间的嵌套 xml 文件转换为数据框

how to convert nested xml file with multiple namespaces in a soap response into a dataframe using python

刚开始学习Python。目前正在学习将 xml 文件转换为数据集,我可以将没有命名空间的 xml 转换为数据框没有问题,但是,对于具有多个命名空间的 xml 来说运气不好。任何指导,建议将不胜感激。示例 xml 文件:

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.../envelope/" 
xmlns:a="http://xxxx.com" 
xmlns:d="http://yyy.com/">
  <soapenv:Header />
  <soapenv:Body>
    <a:item1>
      <a:item2>
        <d:inneritm21>xxx</d:inneritm21>
        <d:inneritm22>yyy</d:inneritm22>
        <d:inneritm23>zzz</d:inneritm23>
        <d:inneritm24>
          <d:inneritm240>
            <d:inneritm241>aa</d:inneritm241>
            <d:inneritm242>bb</d:inneritm242>
            <d:inneritm243>Cc</d:inneritm243>
          </d:inneritm240>
          <d:inneritm240>
            <d:inneritm241>dd</d:inneritm241>
            <d:inneritm242>ee</d:inneritm242>
            <d:inneritm243>ff</d:inneritm243>
          </d:inneritm240>
        </d:inneritm24>
      </a:item2>
      <a:Flag>true</item:Flag>
    </a:item1>
  </soapenv:Body>
</soapenv:Envelope>

我尝试了什么:

xml = ET.parse('c:\myxml.xml')

namespaces={'a':'http://xxxx.com.com',
            'd':'http://yyy.com/'}

with open('c:\myxml.xml', 'r', encoding='utf-8') as f:
    doc = etree.parse(f)
df = []
ws = doc.xpath('.//a:item2', namespaces=namespaces)
if len(ws)>0:
    fc = ws[0].xpath('./d:inneritm24', namespaces=namespaces)
    print(fc)
    for line in fc:
        tmp = []
        cells = line.xpath('.//d:*', namespaces=namespaces)
        for cell in cells:
            print(cell.text)
            tmp.append(cell.text)
        L.append(tmp)
print(df)

我不知道哪里出了问题,只有空 table。所需的输出应如下所示:

inneritm21  inneritm22  inneritm23  inneritm241 inneritm242 inneritm243
0   xxx yyy zzz aa  bb  cc
1   xxx yyy zzz dd  ee  ff

您可以使用递归生成器函数:

import xml.etree.ElementTree as ET, collections
import pandas as pd
d_xml = ET.fromstring(content)[1]
def get_data(d, c = []):
   new_d = collections.defaultdict(list)
   for i in d:
      if not (_c:=list(i)) and not i.tag.endswith('Flag'):
         new_d[0].append((i.tag.split('}')[-1], i.text))
      elif _c:
         new_d[1].append(i)
   if not new_d[1]:
       yield dict(c+new_d[0])
   else:
       for i in new_d[1]:
          yield from get_data(i, c+new_d[0])

df = pd.DataFrame(list(get_data(d_xml)))

输出:

  inneritm21 inneritm22 inneritm23 inneritm241 inneritm242 inneritm243
0        xxx        yyy        zzz          aa          bb          Cc
1        xxx        yyy        zzz          dd          ee          ff