Python:解析ESMA(欧洲金融管理局)XML文件

Python:解析ESMA(欧洲金融管理局)XML文件,python,xml,Python,Xml,我试图解析在此处找到的XML文件: 使用xml.etree.ElementTree.parse() 这些文件包含MiFIR报告法规强制执行的安全ISIN和交易量数据 我无法使用findall()或find()找到任何内容。在孩子和孙子孙女身上绕圈子似乎是可行的,但树的深度是疯狂的 我想提取每个“noneqtytrnspncydata”节点的ISIN和数据。我试过了 from xml.etree.ElementTree import parse tree = parse("FULNCR_2019

我试图解析在此处找到的XML文件:

使用
xml.etree.ElementTree.parse()

这些文件包含MiFIR报告法规强制执行的安全ISIN和交易量数据

我无法使用findall()或find()找到任何内容。在孩子和孙子孙女身上绕圈子似乎是可行的,但树的深度是疯狂的

我想提取每个“noneqtytrnspncydata”节点的ISIN和数据。我试过了

from xml.etree.ElementTree import parse
tree = parse("FULNCR_20191005_D_1of10.xml")
root = tree.getroot()
elems = root.findall('NonEqtyTrnsprncyData')
只给我[]个元素

对于示例数据库
mondial-3.0.xml
使用相同的逻辑在我的第一次努力中就完美地工作了

这里有没有人成功解析过ESMA xml文件,并能促进我的学习

xml文件的简短版本为:

<?xml version="1.0" encoding="UTF-8"?>
<BizData
    xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:head.003.001.01 head.003.001.01.xsd"
    xmlns="urn:iso:std:iso:20022:tech:xsd:head.003.001.01" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Hdr>
        <AppHdr
            xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:head.001.001.01 head.001.001.01_ESMAUG_1.0.0.xsd"
            xmlns="urn:iso:std:iso:20022:tech:xsd:head.001.001.01" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <Fr>
                <OrgId>
                    <Id>
                        <OrgId>
                            <Othr>
                                <Id>EU</Id>
                            </Othr>
                        </OrgId>
                    </Id>
                </OrgId>
            </Fr>
            <To>
                <OrgId>
                    <Id>
                        <OrgId>
                            <Othr>
                                <Id>Public</Id>
                            </Othr>
                        </OrgId>
                    </Id>
                </OrgId>
            </To>
            <BizMsgIdr>FULNCR_20191005_D_3of10</BizMsgIdr>
            <MsgDefIdr>auth.045.001.02</MsgDefIdr>
            <CreDt>2019-10-05T13:00:01Z</CreDt>
        </AppHdr>
    </Hdr>
    <Pyld>
        <Document
            xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:auth.045.001.02 auth.045.001.02_ESMAUG_DATNCR_1.1.0.xsd"
            xmlns="urn:iso:std:iso:20022:tech:xsd:auth.045.001.02" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <FinInstrmRptgNonEqtyTradgActvtyRslt>
                <RptHdr>
                    <RptgNtty>
                        <NtlCmptntAuthrty>EU</NtlCmptntAuthrty>
                    </RptgNtty>
                    <RptgPrd>
                        <FrDtToDt>
                            <FrDt>2019-10-05</FrDt>
                            <ToDt>2019-10-11</ToDt>
                        </FrDtToDt>
                    </RptgPrd>
                </RptHdr>
                <NonEqtyTrnsprncyData>
                    <TechRcrdId>1</TechRcrdId>
                    <Id>CH0110680714</Id>
                    <FinInstrmClssfctn>BOND</FinInstrmClssfctn>
                    <RptgPrd>
                        <FrDtToDt>
                            <FrDt>2018-01-01</FrDt>
                            <ToDt>2018-03-31</ToDt>
                        </FrDtToDt>
                    </RptgPrd>
                    <Lqdty>false</Lqdty>
                </NonEqtyTrnsprncyData>
            </FinInstrmRptgNonEqtyTradgActvtyRslt>
        </Document>
    </Pyld>
</BizData>

欧盟
公开的
FULNCR_20191005_D_3of10
auth.045.001.02
2019-10-05T13:00:01Z
欧盟
2019-10-05
2019-10-11
1.
CH0110680714
债券
2018-01-01
2018-03-31
假的

其中我删除了除一个之外的所有非QTYTRNSPNCYDATA元素。

这里有两个问题:

  • 只有标记名的
    Element.findall()
    只能找到直接子级;从:

    Element.findall()

    你想在这里用一个代替;在标记名前面加上
    /
    会告诉API在当前元素下面的所有级别上搜索子元素

  • XML文档使用;您正在查找的元素是
    urn:iso:std:iso:20022:tech:xsd:auth.045.001.02
    命名空间的一部分;这是使用
    xmlns=“…”
    属性在
    Document
    父元素上设置的,该属性如下所示(忽略其他属性):

    
    
    xmlns
    属性,无论是否带有前缀(例如
    xmlns:prefix
    ),都应用于它们所定义的元素和整个子树,直到另一个此类属性覆盖该设置

    请注意,诸如
    xsi
    之类的前缀通常是文档本地的,因此前缀是什么并不重要;命名名称空间的是URI

因此,您希望使用名称空间,并且希望使用XPath表达式。使用(您自己的)前缀最容易使编写XPath表达式更容易。这将找到您的元素:

namespace = 'urn:iso:std:iso:20022:tech:xsd:auth.045.001.02'
elems = tree.findall('.//ns:NonEqtyTrnsprncyData', {'ns': namespace})
您还可以使用
/{urn:iso:std:iso:20022:tech:xsd:auth.045.001.02}noneqtytrnspncydata
作为表达式,并且不使用名称空间前缀和映射,但在多次使用时会变得非常冗长

您也不需要调用
tree.getroot()
;您可以直接使用
tree.findall()
,因为我们使用的XPath表达式旨在搜索整个树

演示:

您可能还想看看,它构建在相同的ElementTree API上,但速度更快,并提供了更多功能,例如更好的命名空间处理和完整的XPath 1.0支持(Python标准库ElementTree实现的限制更大)

>>> from xml.etree.ElementTree import parse
>>> tree = parse("FULNCR_20191005_D_1of10.xml")
>>> namespace = 'urn:iso:std:iso:20022:tech:xsd:auth.045.001.02'
>>> elems = tree.findall('.//ns:NonEqtyTrnsprncyData', {'ns': namespace})
>>> len(elems)
1
>>> elems[0]
<Element '{urn:iso:std:iso:20022:tech:xsd:auth.045.001.02}NonEqtyTrnsprncyData' at 0x109a84400>
>>> list(elems[0])
[<Element '{urn:iso:std:iso:20022:tech:xsd:auth.045.001.02}TechRcrdId' at 0x109a844a0>, <Element '{urn:iso:std:iso:20022:tech:xsd:auth.045.001.02}Id' at 0x109a84540>, <Element '{urn:iso:std:iso:20022:tech:xsd:auth.045.001.02}FinInstrmClssfctn' at 0x109a845e0>, <Element '{urn:iso:std:iso:20022:tech:xsd:auth.045.001.02}RptgPrd' at 0x109a84680>, <Element '{urn:iso:std:iso:20022:tech:xsd:auth.045.001.02}Lqdty' at 0x109a849a0>]
>>> prefix, has_namespace, remainder = elems[0].tag.partition("}")
>>> if has_namespace:
...     namespace, tag = prefix[1:], remainder
... else:
...     namespace, tag = None, prefix
...
>>> namespace, tag
('urn:iso:std:iso:20022:tech:xsd:auth.045.001.02', 'NonEqtyTrnsprncyData')