Сглаживание вложенных XML при сохранении родительско-дочерних отношений между двумя тегами - PullRequest
1 голос
/ 06 мая 2020

У меня есть несколько xml с вложенными атрибутами

<Music>
  <Groups>
    <Artist>The Beatles</Artist>
    <Releases>
      <Release album="Abbey Road" year="1969" />
      <Release album="The White Album" year="1968" />
    </Releases>
  </Groups>
  <Groups>
    <Artist>Bob Dylan</Artist>
    <Releases>
      <Release album="Blonde on Blonde" year="1966" />
      <Release album="Blood on the Tracks" year="1975" />
    </Releases>
  </Groups>
  <Groups>
    <Artist>The Rolling Stones</Artist>
    <Releases>
      <Release album="Sticky Fingers" year="1971" />
      <Release album="Exile On Main Street" year="1972" />
    </Releases>
  </Groups>
</Music>

Я пытаюсь вернуть шестистрочный фрейм данных, однако он создает отношения «многие ко многим», где каждый исполнитель назначается каждому альбому. Вот мой код и мой неверный результат:

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

tree=et.parse(r'music.xml')
root=tree.getroot()

Artists=[]
AlbumTitle=[]
ReleaseYear=[]

for x in root.iter('Artist'):
    root1=et.Element('root')
    root1=x
    for records in root.iter('Release'):
        root2=et.Element('root')
        root2=records
        AlbumTitle.append(records.attrib['album'])
        ReleaseYear.append(records.attrib['year'])
        Artists.append(x.text)

df = pd.DataFrame({'Artists': Artists, 
                   'AlbumTitle': AlbumTitle,
                   'ReleaseYear': ReleaseYear})

Current output:

Artists                         AlbumTitle          ReleaseYear
-------                         -----------           -----         
1   The Beatles                 Abbey Road              1969
2   The Beatles                 The White album         1968
3   The Beatles                 Blonde On Blonde        1966
4   The Beatles                 Blood on The tracks     1975
5   The Beatles                 Sticky Fingers          1971
6   The Beatles                 Exile On Main Street    1972
7   Bob Dylan                   Abbey Road              1969
8   Bob Dylan                   The White album         1968
...                             ...                     ...
18  The Rolling Stones          Exile On Main Street    1972 


Target output:

Artists               AlbumTitle            ReleaseYear
-------               -----------           -----           
1 The Beatles         Abbey Road            1969
2 The Beatles         The White album       1968
3 Bob Dylan           Blonde On Blonde      1966
4 Bob Dylan           Blood on The tracks   1975
5 The Rolling Stones  Sticky Fingers        1971
6 The Rolling Stones  Exile On Main Street  1972

Я прочитал документацию ElementTree, чтобы увидеть, как Artists.append может иметь строгую взаимосвязь при объединении с двумя атрибутами, но пока безуспешно. Любая помощь будет принята с благодарностью, спасибо

Ответы [ 2 ]

1 голос
/ 06 мая 2020
import xml.etree.ElementTree as ET
#i wrapped the xml into a 'data' variable in string form
#since u r reading it from a file getroot should suffice : 
#root = ET.parse(xmlfile).getroot()

root = ET.fromstring(data)  

d = []
#the main point is the 'Groups' section
for ent in root.findall('Groups'):
    #get the Artist names
    name = ent.find('Artist').text
    #append each entry in the Release section :
    for entry in ent.findall('.//Release'):
        #add a name key with the artist name to each entry
        entry.attrib.update({'name':name})
        d.append(entry.attrib)

#get dataframe
#u can rename the columns to ur taste
pd.DataFrame(d)

       album                year    name
0   Abbey Road              1969    The Beatles
1   The White Album         1968    The Beatles
2   Blonde on Blonde        1966    Bob Dylan
3   Blood on the Tracks     1975    Bob Dylan
4   Sticky Fingers          1971    The Rolling Stones
5   Exile On Main Street    1972    The Rolling Stones
1 голос
/ 06 мая 2020

Это должно сработать для вас:

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

tree=et.parse(r'music.xml')
root=tree.getroot()

Artists=[]
AlbumTitle=[]
ReleaseYear=[]

for group in root.iter('Groups'):
    # Groups
    artist = group[0].text
    releases = group[1]
    for release in releases:
        Artists.append(artist)
        AlbumTitle.append(release.attrib['album'])
        ReleaseYear.append(release.attrib['year'])

df = pd.DataFrame({'Artists': Artists,
                   'AlbumTitle': AlbumTitle,
                   'ReleaseYear': ReleaseYear})

Это документация о том, как анализировать xml (https://docs.python.org/3.4/library/xml.etree.elementtree.html)

Вывод:

              Artists            AlbumTitle ReleaseYear
0         The Beatles            Abbey Road        1969
1         The Beatles       The White Album        1968
2           Bob Dylan      Blonde on Blonde        1966
3           Bob Dylan   Blood on the Tracks        1975
4  The Rolling Stones        Sticky Fingers        1971
5  The Rolling Stones  Exile On Main Street        1972
...