Вложенный XML со всеми данными в качестве атрибутов для pandas dataframe, импортируется только последняя запись - PullRequest
0 голосов
/ 20 ноября 2018

Редактировать: проблема решена, обновленный код ниже.

Я потратил несколько дней на поиски в интернете, пытаясь понять это, и, похоже, я ничего не могу найти.

В основном у меня есть сильно вложенный XML-файл со всей информацией, которую я хочу извлечь, включенной в качестве атрибутов, пример ниже:

<TotalAllocationResultDocument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" DtdRelease="0" DtdVersion="4" xsi:noNamespaceSchemaLocation="total-allocation-result-document.xsd">
  <DocumentIdentification v="A_R-GB-NI-Q-BASE-------190101-01"/>
  <DocumentVersion v="1"/>
  <DocumentType v="A25"/>
  <SenderIdentification codingScheme="A01" v="10X1001A1001A57U"/>
  <SenderRole v="A07"/>
  <ReceiverIdentification codingScheme="A01" v="10XNITSO-12345-O"/>
  <ReceiverRole v="A04"/>
  <CreationDateTime v="2018-11-13T12:55:08Z"/>
  <BidTimeInterval v="2018-12-31T23:00Z/2019-03-31T22:00Z"/>
  <Domain codingScheme="A01" v="10YDOM-1010A024Y"/>
  <AllocationTimeSeries>
    <TimeSeriesIdentification v="TotalAllocationResults_TS_4888599"/>
    <BidDocumentIdentification v="GB-NI-Q-BASE-------190101-01"/>
    <BidDocumentVersion v="1"/>
    <BidIdentification v="BID00001-GB-NI"/>
    <BiddingParty codingScheme="A01" v="xxxxxxxxxx"/>
    <AuctionIdentification v="GB-NI-Q-BASE-------190101-01"/>
    <BusinessType v="A03"/>
    <InArea codingScheme="A01" v="10Y1001A1001A016"/>
    <OutArea codingScheme="A01" v="10YGB----------A"/>
    <ContractType v="A08"/>
    <ContractIdentification v="311218D3-GB-NI-FK01"/>
    <MeasureUnitQuantity v="MAW"/>
    <Currency v="EUR"/>
    <MeasureUnitPrice v="MWH"/>
    <Period>
      <TimeInterval v="2018-12-31T23:00Z/2019-03-31T22:00Z"/>
      <Resolution v="P3M"/>
      <Interval>
        <Pos v="1"/>
        <Qty v="0"/>
        <PriceAmount v="4.02"/>
        <BidQty v="3.0"/>
        <BidPriceAmount v="2.51"/>
      </Interval>
    </Period>
  </AllocationTimeSeries>
  <AllocationTimeSeries>
    <TimeSeriesIdentification v="TotalAllocationResults_TS_4888602"/>
    <BidDocumentIdentification v="GB-NI-Q-BASE-------190101-01"/>
    <BidDocumentVersion v="1"/>
    <BidIdentification v="BID00004-GB-NI"/>
    <BiddingParty codingScheme="A01" v="yyyyyyyyyy"/>
    <AuctionIdentification v="GB-NI-Q-BASE-------190101-01"/>
    <BusinessType v="A03"/>
    <InArea codingScheme="A01" v="10Y1001A1001A016"/>
    <OutArea codingScheme="A01" v="10YGB----------A"/>
    <ContractType v="A08"/>
    <ContractIdentification v="311218D3-GB-NI-FK01"/>
    <MeasureUnitQuantity v="MAW"/>
    <Currency v="EUR"/>
    <MeasureUnitPrice v="MWH"/>
      <Period>
      <TimeInterval v="2018-12-31T23:00Z/2019-03-31T22:00Z"/>
      <Resolution v="P3M"/>
      <Interval>
        <Pos v="1"/>
        <Qty v="0"/>
        <PriceAmount v="4.02"/>
        <BidQty v="3.0"/>
        <BidPriceAmount v="1.51"/>
      </Interval>
    </Period>
  </AllocationTimeSeries>
</TotalAllocationResultDocument>

Я пытаюсь получить эти данные в пандас, с такими столбцами, как:

SenderIdentification | DocumentIdentification | InArea | BidID | AllocatedQty

Код, который я получил, основан на загрузке различных источников, но выглядит так:

import pandas as pd
import xml.etree.cElementTree as et

def getvalueofnode(node):
    """ return node text or None """
    return node.text if node is not None else None

def main():
    """ main """
    parsed_xml =et.parse("example.xml")
    dfcols = ['SenderIdentification', 'DocumentIdentification', 'InArea', 'BidID', 'AllocatedQty']
    df_xml = pd.DataFrame(columns=dfcols)

    for node in parsed_xml.getroot():

        for SenderIdentificationFind in parsed_xml.findall('./SenderIdentification'):
            SenderIdentification = SenderIdentificationFind.get('v')

        for DocumentIdentificationFind in parsed_xml.findall('./DocumentIdentification'):
            DocumentIdentification = DocumentIdentificationFind.get('v')

        for InAreaFind in parsed_xml.findall('./AllocationTimeSeries/InArea'):
            InArea = InAreaFind.get('v')

        for BidIDFind in parsed_xml.findall('./AllocationTimeSeries/BidIdentification'):
            BidID = BidIDFind.get('v')

        for BidIDFind in parsed_xml.findall('./AllocationTimeSeries/Period/Interval/Qty'):
            AllocatedQty = BidIDFind.get('v')

        df_xml = df_xml.append(
            pd.Series([SenderIdentification, DocumentIdentification, InArea, BidID, AllocatedQty], index=dfcols),
            ignore_index=True)

    return df_xml

main()

df_xml = main()

Это создает фрейм данных, но, похоже, извлекает данные только из последней записи «AllocationTimeSeries» в XML и, похоже, содержит гораздо больше записей, чем общее количество записей «AllocationTimeSeries» в документе (например, I будет ожидать две уникальные строки, основанные на данных этого примера, но на самом деле я вижу 12 одинаковых строк).

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

Я также попробовал подход с использованием файла XLST для упрощения синтаксического анализа файла XLS до более простого формата, но у меня нет достаточных знаний XLS, чтобы заставить это работать.

Спасибо!

Код, который работает:

import pandas as pd
import lxml.etree as et

def getvalueofnode(node):
    """ return node text or None """
    return node.text if node is not None else None

def main():
    """ main """
    parsed_xml = et.parse("example.xml")
    dfcols = ['DocumentIdentification', 'DocumentVersion', 'CreationDateTime', 'BidTimeInterval', 'BidIdentification', 'BiddingParty', 'OutArea', 'InArea', 'ContractIdentification', 'BidPrice', ' BidQuantity', 'ClearingPrice', 'AllocatedQuantity']
    df_xml = pd.DataFrame(columns=dfcols)

    root = parsed_xml.getroot()
    result = len(root.findall("./AllocationTimeSeries"))+1

    for DocumentIdentificationFind in parsed_xml.findall('./DocumentIdentification'):
        DocumentIdentification = DocumentIdentificationFind.get('v')

    for DocumentVersionFind in parsed_xml.findall('./DocumentVersion'):
        DocumentVersion = DocumentVersionFind.get('v')

    for CreationDateTimeFind in parsed_xml.findall('./CreationDateTime'):
        CreationDateTime = CreationDateTimeFind.get('v')

    for BidTimeIntervalFind in parsed_xml.findall('./BidTimeInterval'):
        BidTimeInterval = BidTimeIntervalFind.get('v')

    for i in range(1,result):

        BidIdentificationString = './AllocationTimeSeries[%d]/BidIdentification'%(i)
        BiddingPartyString = './AllocationTimeSeries[%d]/BiddingParty'%(i)
        InAreaString = './AllocationTimeSeries[%d]/InArea'%(i)
        OutAreaString = './AllocationTimeSeries[%d]/OutArea'%(i)
        ContractIdentificationString = './AllocationTimeSeries[%d]/ContractIdentification'%(i)
        BidPriceString = './AllocationTimeSeries[%d]/Period/Interval/BidPriceAmount'%(i)
        BidQuantityString = './AllocationTimeSeries[%d]/Period/Interval/BidQty'%(i)
        ClearingPriceString = './AllocationTimeSeries[%d]/Period/Interval/PriceAmount'%(i)
        AllocatedQuantityString = './AllocationTimeSeries[%d]/Period/Interval/Qty'%(i)

        for BidIdentificationFind in parsed_xml.findall(BidIdentificationString):
            BidIdentification = BidIdentificationFind.get('v')

        for BiddingPartyFind in parsed_xml.findall(BiddingPartyString):
            BiddingParty = BiddingPartyFind.get('v')

        for InAreaFind in parsed_xml.findall(InAreaString):
            InArea = InAreaFind.get('v')

        for OutAreaFind in parsed_xml.findall(OutAreaString):
            OutArea = OutAreaFind.get('v')

        for ContractIdentificationFind in parsed_xml.findall(ContractIdentificationString):
            ContractIdentification = ContractIdentificationFind.get('v')

        for BidPriceFind in parsed_xml.findall(BidPriceString):
            BidPrice = BidPriceFind.get('v')

        for BidQuantityFind in parsed_xml.findall(BidQuantityString):
            BidQuantity = BidQuantityFind.get('v')

        for ClearingPriceFind in parsed_xml.findall(ClearingPriceString):
            ClearingPrice = ClearingPriceFind.get('v')

        for AllocatedQuantityFind in parsed_xml.findall(AllocatedQuantityString):
            AllocatedQuantity = AllocatedQuantityFind.get('v')

        df_xml = df_xml.append(
            pd.Series([DocumentIdentification, DocumentVersion, CreationDateTime, BidTimeInterval, BidIdentification, BiddingParty, OutArea, InArea, ContractIdentification, BidPrice, BidQuantity, ClearingPrice, AllocatedQuantity], index=dfcols),
            ignore_index=True)

    return df_xml

main()

df_xml = main()

df_xml
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...