python разбирать xml файлы из евростата sdmx - PullRequest
0 голосов
/ 02 февраля 2020

Я пытаюсь проанализировать данные евростата, полученные из их sdmx webservice .

Пример необработанного файла: 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 + request + l xml + 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'}]

Я пытаюсь поместить объект результата в хорошо отформатированный pandas фрейм данных, но я застрял с этим.

Любая подсказка для меня, пожалуйста?

Дополнительный вопрос: я думаю, библиотека xmlschema могла бы помочь мне разобрать xml, если я смогу получить файл xsd, связанный с моим xml файлом. Я неправильно истолковал возможности этой библиотеки?

1 Ответ

0 голосов
/ 09 февраля 2020

Я нахожу способ достичь своей цели, но это решение нужно улучшить.

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
...