【问题标题】:Reading deeply nested xml with Pandas使用 Pandas 读取深度嵌套的 xml
【发布时间】:2021-11-08 23:04:40
【问题描述】:

我保证我已经在 stackoverflow 中看到了读取 XML 的不同示例,但没有一个对我有用。我正在阅读一个看起来像这样的 xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<ASSETS ASOF_DATE="10/22/2021" CREATE_DATE="10/22/2021" RECORDS="140">
    <ASSET><EQUITY_EQUITY>
        <ACCRUAL_DT>12/1/2009</ACCRUAL_DT>
        <ASSET_BENCHMARK>BRT6U6V13</ASSET_BENCHMARK>
        <CALC_TYPE>0</CALC_TYPE>
        <CD_INSTMT_TYPE>UNKNOWN</CD_INSTMT_TYPE>
        <CHANGE_DT>10/22/2021 0:14:46.800</CHANGE_DT>
        <COMPOUND_FLAG>0</COMPOUND_FLAG>
        <COUNTRY>US</COUNTRY>
        <CURRENCY>USD</CURRENCY>
        <CUSIP>464286400</CUSIP>
        <CUSIP2_set SIZE="6">
            <CUSIP2_record>
                <CODE>A</CODE>
                <IDENTIFIER>464286400</IDENTIFIER>
            </CUSIP2_record>
            <CUSIP2_record>
                <CODE>C</CODE>
                <IDENTIFIER>2726014</IDENTIFIER>
            </CUSIP2_record>
            <CUSIP2_record>
                <CODE>I</CODE>
                <IDENTIFIER>US4642864007</IDENTIFIER>
            </CUSIP2_record>
            <CUSIP2_record>
                <CODE>R</CODE>
                <IDENTIFIER>EWZ.P</IDENTIFIER>
            </CUSIP2_record>
            <CUSIP2_record>
                <CODE>g</CODE>
                <IDENTIFIER>1I_EWZ_*</IDENTIFIER>
            </CUSIP2_record>
            <CUSIP2_record>
                <CODE>2</CODE>
                <IDENTIFIER>EWZ US</IDENTIFIER>
            </CUSIP2_record>
        </CUSIP2_set>
        <CUSIP_ALIAS_set SIZE="2">
            <CUSIP_ALIAS_record>
                <CODE>42</CODE>
                <IDENTIFIER>464286400</IDENTIFIER>
                <PURPOSE>CUSIP</PURPOSE>
            </CUSIP_ALIAS_record>
            <CUSIP_ALIAS_record>
                <CODE>70</CODE>
                <IDENTIFIER>US4642864007</IDENTIFIER>
                <PURPOSE>ISIN</PURPOSE>
            </CUSIP_ALIAS_record>
        </CUSIP_ALIAS_set>
        <CUSIP_TYPE>CUSIP</CUSIP_TYPE>
        <DESC_INSTMT>ISHARES MSCI BRAZIL ETF</DESC_INSTMT>
        <DESC_INSTMT2>ETF-E</DESC_INSTMT2>
        <DR_TYPE>N</DR_TYPE>
        <EXCHANGE>NYSEARC</EXCHANGE>
        <FLAG_144A>N</FLAG_144A>
        <FLAG_PERFORMING>Y</FLAG_PERFORMING>
        <ISSUER_ID>E96351</ISSUER_ID>
        <ISSUE_DT>12/1/2009</ISSUE_DT>
        <LIQUIDITY>L</LIQUIDITY>
        <MARKET>US</MARKET>
        <MARKET_MIC>ARCX</MARKET_MIC>
        <MIN_LOT_SIZE>1</MIN_LOT_SIZE>
        <MIN_TRD_SIZE>1</MIN_TRD_SIZE>
        <MODIFIED_BY>sm_timestamp</MODIFIED_BY>
        <MTN>N</MTN>
        <NTL_FLAG>N</NTL_FLAG>
        <PMT_FREQ_TYPE>0</PMT_FREQ_TYPE>
        <PRICE_AS_PCT>N</PRICE_AS_PCT>
        <PRICING>100ths</PRICING>
        <REVIEWED_BY>f2socamp</REVIEWED_BY>
        <SECTOR_set SIZE="2">
            <SECTOR_record>
                <CODE>295</CODE>
                <LEVEL>16</LEVEL>
                <TYPE>COVERAGE</TYPE>
            </SECTOR_record>
            <SECTOR_record>
                <CODE>NARC</CODE>
                <LEVEL>1</LEVEL>
                <TYPE>REUT_SEGM</TYPE>
            </SECTOR_record>
        </SECTOR_set>
        <SEC_TYPE>EQUITY_EQUITY</SEC_TYPE>
        <SM_SEC_GROUP>EQUITY</SM_SEC_GROUP>
        <SM_SEC_TYPE>EQUITY</SM_SEC_TYPE>
        <TICKER>EWZ</TICKER>
        <WI_FLAG>N</WI_FLAG>
    </EQUITY_EQUITY></ASSET>
    </ASSETS>

标准

df = pd.read_xml(file, xpath='.//ASSET') 

给了我一个相当不错的数据框,但我丢失了我想要的信息,这是:

<CUSIP2_record>
                <CODE>g</CODE>
                <IDENTIFIER>1I_EWZ_*</IDENTIFIER>

(这是嵌套在&lt;CUSIP2_set SIZE="6"&gt; 标签内。

我得到的数据框将CUSIP2_set 列读取为Nan,但理论上该变量应该是一个列表,因为CUSIP2_set 中有很多变量,如示例文件中所示。

ET 库也不工作。如果我这样做:


import xml.etree.ElementTree as ET
import pandas as pd
data = 'blabla.xml'
tree = ET.parse(data)
root = tree.getroot()

for cusip in root.iter('CUSIP'): 
  print(cusip.attrib) 

我得到了空字典。

我想要一个这样的数据框(我使用的是整个文件,如果你只使用这个例子,你只会有一行):

除了 CUSIP2_set 列不能为空。 (我的代码里全是 Np.Nan 的)。

对我有用的是 CUSIP2_set 列包含来自该子字段的相关代码(在示例文件中,此记录是:&lt;CUSIP2_record&gt; &lt;CODE&gt;g&lt;/CODE&gt; &lt;IDENTIFIER&gt;1I_EWZ_*&lt;/IDENTIFIER&gt;;

我只需要1I_EWZ_* 部分)。

此列还可以包含一个列表,其中包含 CUSIP2_set 中的所有变量(所有子字段)。

【问题讨论】:

  • 您使用 pandas 是因为您想将 XML 用于数据科学或类似的东西吗?或者您只是想以任何可能的方式在 Python 中解析 XML?
  • 您能否编辑您的问题以包含 XML 示例中的预期数据框? XML 是一种复杂的格式,并不是每个布局都与pd.read_xml 兼容。
  • @user17242583 我只是想以任何可能的方式解析它。
  • @CodeDifferent 是的!你是对的。感谢您指出了这一点。让我现在编辑问题。

标签: python pandas xml


【解决方案1】:

您可以使用 xmltodictflatten_json 执行此操作

将您的 xml 设置为 xmltoparse(任何变量名都可以作为字符串)

import xmltodict
from flatten_json import flatten
#this will create a json object
data = json.loads(json.dumps(xmltodict.parse(xmltoparse)))

# this will put all items into a single row
dic_flattened = (flatten(d, '.') for d in [data])
df = pd.DataFrame(dic_flattened)

输出

  ASSETS.@ASOF_DATE ASSETS.@CREATE_DATE ASSETS.@RECORDS  ... ASSETS.ASSET.EQUITY_EQUITY.SM_SEC_TYPE ASSETS.ASSET.EQUITY_EQUITY.TICKER ASSETS.ASSET.EQUITY_EQUITY.WI_FLAG
0        10/22/2021          10/22/2021             140  ...                                 EQUITY                               EWZ                                  N

[1 rows x 65 columns]

不同的观点

In [67]: df.iloc[0]
Out[67]:
ASSETS.@ASOF_DATE                                10/22/2021
ASSETS.@CREATE_DATE                              10/22/2021
ASSETS.@RECORDS                                         140
ASSETS.ASSET.EQUITY_EQUITY.ACCRUAL_DT             12/1/2009
ASSETS.ASSET.EQUITY_EQUITY.ASSET_BENCHMARK        BRT6U6V13
                                                  ...
ASSETS.ASSET.EQUITY_EQUITY.SEC_TYPE           EQUITY_EQUITY
ASSETS.ASSET.EQUITY_EQUITY.SM_SEC_GROUP              EQUITY
ASSETS.ASSET.EQUITY_EQUITY.SM_SEC_TYPE               EQUITY
ASSETS.ASSET.EQUITY_EQUITY.TICKER                       EWZ
ASSETS.ASSET.EQUITY_EQUITY.WI_FLAG                        N
Name: 0, Length: 65, dtype: object

【讨论】:

  • 你知道为什么我会收到这个错误:``` File "", line 1, in File "/usr/local/lib/python3.9/site -packages/xmltodict.py”,第 327 行,解析中 parser.Parse(xml_input, True) xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 0```?
  • 不,不是。这是说 xml 格式不正确。您是否将其作为字符串传递?在它周围使用三个单引号?我就是这样让你有足够的工作量的。否则,您的示例可能无法完全代表您的实际 xml。
猜你喜欢
  • 1970-01-01
  • 2022-07-10
  • 1970-01-01
  • 1970-01-01
  • 2019-05-24
  • 1970-01-01
  • 2013-06-08
  • 2014-02-24
  • 2023-03-06
相关资源
最近更新 更多