-1

我尝试解析来自他们的sdmx webservice的 eurostat 数据。

原始文件示例: http: //ec.europa.eu/eurostat/SDMX/diss-web/rest/data/nrg_bal_c/A.PPRD+IMP.TOTAL.KTOE.FR/ ?startPeriod=2016

<?xml version='1.0' encoding='UTF-8'?><message:GenericData xmlns:footer="http://www.sdmx.org/resources/sdmxml/schemas/v2_1/message/footer" xmlns:generic="http://www.sdmx.org/resources/sdmxml/schemas/v2_1/data/generic" xmlns:common="http://www.sdmx.org/resources/sdmxml/schemas/v2_1/common" xmlns:message="http://www.sdmx.org/resources/sdmxml/schemas/v2_1/message" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xml="http://www.w3.org/XML/1998/namespace"><message:Header><message:ID>c79d0c159af023563e604b59c443b622</message:ID><message:Test>false</message:Test><message:Prepared>2020-02-05T08:16:58</message:Prepared><message:Sender id="ESTAT"><common:Name xml:lang="en">Eurostat</common:Name><message:Timezone>+01:00</message:Timezone></message:Sender><message:Receiver id="RECEIVER"/><message:Structure structureID="ESTAT_DSD_nrg_bal_c_1_0" dimensionAtObservation="TIME_PERIOD"><common:Structure><Ref agencyID="ESTAT" id="DSD_nrg_bal_c" version="1.0"/></common:Structure></message:Structure><message:DataSetAction>Append</message:DataSetAction><message:DataSetID>nrg_bal_c</message:DataSetID></message:Header><message:DataSet structureRef="ESTAT_DSD_nrg_bal_c_1_0"><generic:Series><generic:SeriesKey><generic:Value id="UNIT" value="KTOE"/><generic:Value id="SIEC" value="TOTAL"/><generic:Value id="NRG_BAL" value="IMP"/><generic:Value id="GEO" value="FR"/><generic:Value id="FREQ" value="A"/></generic:SeriesKey><generic:Obs><generic:ObsDimension value="2018"/><generic:ObsValue value="152791.215"/></generic:Obs><generic:Obs><generic:ObsDimension value="2017"/><generic:ObsValue value="157271.627"/></generic:Obs><generic:Obs><generic:ObsDimension value="2016"/><generic:ObsValue value="151967.722"/></generic:Obs></generic:Series><generic:Series><generic:SeriesKey><generic:Value id="UNIT" value="KTOE"/><generic:Value id="SIEC" value="TOTAL"/><generic:Value id="NRG_BAL" value="PPRD"/><generic:Value id="GEO" value="FR"/><generic:Value id="FREQ" value="A"/></generic:SeriesKey><generic:Obs><generic:ObsDimension value="2018"/><generic:ObsValue value="137928.128"/></generic:Obs><generic:Obs><generic:ObsDimension value="2017"/><generic:ObsValue value="131845.752"/></generic:Obs><generic:Obs><generic:ObsDimension value="2016"/><generic:ObsValue value="133737.071"/></generic:Obs></generic:Series></message:DataSet></message:GenericData>

我使用 python + requests + lxml + pandas 库(只有这个,我公司不允许第三方库,如 pandasdmx)。我可能会使用 xmlschema。

root = etree.fromstring(response.content)
dataset = root.getchildren()[1]
result = [elem.attrib for elem in dataset.iter()]

结果如下所示:

[{'structureRef': 'ESTAT_DSD_nrg_bal_c_1_0'},
 {},
 {},
 {'id': 'UNIT', 'value': 'KTOE'},
 {'id': 'SIEC', 'value': 'TOTAL'},
 {'id': 'NRG_BAL', 'value': 'IMP'},
 {'id': 'GEO', 'value': 'FR'},
 {'id': 'FREQ', 'value': 'A'},
 {},
 {'value': '2018'},
 {'value': '152791.215'},
 {},
 {'value': '2017'},
 {'value': '157271.627'},
 {},
 {'value': '2016'},
 {'value': '151967.722'},
 {},
 {},
 {'id': 'UNIT', 'value': 'KTOE'},
 {'id': 'SIEC', 'value': 'TOTAL'},
 {'id': 'NRG_BAL', 'value': 'PPRD'},
 {'id': 'GEO', 'value': 'FR'},
 {'id': 'FREQ', 'value': 'A'},
 {},
 {'value': '2018'},
 {'value': '137928.128'},
 {},
 {'value': '2017'},
 {'value': '131845.752'},
 {},
 {'value': '2016'},
 {'value': '133737.071'}]

我尝试将结果对象放在格式良好的熊猫数据框中,但我坚持这一点。

请问有什么线索吗?

奖励问题:如果我能获得与我的 xml 文件相关的 xsd 文件,我认为 xmlschema 库可以帮助我解析 xml。我是否误解了这个库的功能?

4

2 回答 2

1

有点晚了,但是已经有一个 python 包可以帮助您从 Eurostat SDMX 服务获取数据:https ://pypi.org/project/eurostat/

于 2020-06-23T08:12:26.697 回答
0

我找到了实现目标的方法,但是这个解决方案需要改进。

nbSerie = int(root.xpath('count(.//generic:Series)', namespaces=ns))

dim = []
obs = []

for i in range(nbSerie):
     serieskey = root.getchildren()[1][i].xpath(".//generic:Value/@id|.//generic:Value/@value", namespaces=ns)
     values = root.getchildren()[1][i].xpath(".//generic:ObsDimension/@value|.//generic:ObsValue/@value", namespaces=ns)
     dim.append(serieskey)
     obs.append(values)

from itertools import chain

a=list(chain(*list(chain(*list(zip(dim, obs))))))
b=list(zip(a[::2], a[1::2]))

from collections import defaultdict

data_dic = defaultdict(list)
for k, v in b:
     data_dic[k].append(v)

df = pd.DataFrame(data_dic)
df
于 2020-02-09T07:34:14.277 回答