2

我正在尝试使用 python 库lxml解析 XML ,并希望结果输出位于数据框中。我对 python 和解析比较陌生,所以在我概述问题时请多多包涵。我尝试解析的原始 xml 可在此处获得

我有兴趣在“ invstOrSec ”中获得一些相关标签。下面是“ invstOrSec ”的一个实例的快照,其中标签“ curCd ”附带的文本是美元。

<?xml version="1.0" encoding="UTF-8"?>
    <invstOrSec>
        <name>NIPPON LIFE INSURANCE</name>
        <lei>549300Y0HHMFW3EVWY08</lei>
        <curCd>USD</curCd>
    <invstOrSec>

这相对简单,我目前的方法包括首先在字典中定义相关标签,然后将它们粗化为循环中的数据帧。

    import pandas as pd
    from lxml import etree

    # Declare directory
    os.chdir('C:/Users/A1610222/Desktop/Form NPORT/pkg/sec-edgar-filings/0001548717/NPORT-P/0001752724- 
    20-040624')

    # Set root
    xmlfile = "filing-details.xml"
    tree = etree.parse(xmlfile)
    root = tree.getroot()

    # Remove namespace prefixes
    for elem in root.getiterator():
        elem.tag = etree.QName(elem).localname
   
    # Remove unused namespace declarations
    etree.cleanup_namespaces(root)

    # Set path
    invstOrSec = root.xpath('//invstOrSec')

    # Define tags to extract
    vars = {'invstOrSec' : {'name', 'lei', 'curCd'}

    # Extract holdings data
    sec_info =  pd.DataFrame()
    temp = pd.DataFrame()

    for one in invstOrSec:
        for two in one:
            if two.tag in vars['invstOrSec']:
                temp[two.tag] = [two.text]
        sec_info = sec_info.append(temp)  

这是sec_info的前三行

姓名 curCd
日本人寿保险 549300Y0HHMFW3EVWY08 美元
劳埃德银行集团 549300PPXHEU2JF0AM85 美元
安桥公司 98TPTUM4IVMFCZBCUR27 美元

但是,当货币不是美元时,xml 的结构略有不同。请参见下面的示例。

<?xml version="1.0" encoding="UTF-8"?>
    <invstOrSec>
        <name>ACHMEA BV</name>
        <lei>7245007QUMI1FHIQV531</lei>
        <currencyConditional curCd="EUR" exchangeRt="0.89150400"/>
    <invstOrSec>

这次curCd被一个不同的标签 currencyConditional替换,它包含与文本相反的属性。我很难解释这些情况,同时保持我的代码尽可能通用。我希望我已经设法说明了这个问题。再次,如果这太初级,请原谅我。任何帮助将非常感激。

4

1 回答 1

0

这是您不应该尝试重新发明轮子的一种情况。使用别人开发的工具...

import pandas as pd
import pandas_read_xml as pdx

url = 'https://www.sec.gov/Archives/edgar/data/1548717/000175272420040624/primary_doc.xml'

df = pdx.read_xml(url,['edgarSubmission', 'formData', 'invstOrSecs','invstOrSec'])

#because of the non-US currency column, you have to apply one more contortion:
df['currencyConditional'] = df['currencyConditional'].apply(lambda x: x.get('@curCd') if not isinstance(x,float) else "NA" )
df[['name','lei','curCd','currencyConditional']]

输出(显然是部分的) - 注意最后一行:

168     BNP PARIBAS     R0MUWSFPU8MPRO8K5P83    USD     NA
169     Societe Generale    O2RNE8IBXP4R0TD8PU41    USD     NA
170     BARCLAYS PLC    213800LBQA1Y9L22JB70    NaN     GBP
于 2021-03-09T03:01:14.613 回答