Search code examples
python-3.xxmlpandasdataframedata-extraction

Extracting data from a xml file into a dataframe


I'm trying to extract some data from a xml file, here's a sample from the file (it's quite big).

```<?xml version="1.0" encoding="UTF-8" ?>
<revista numero="2558" data="14/01/2020">
  <processo numero="909359539" data-deposito="11/05/2015" data-concessao="14/01/2020" data-vigencia="14/01/2030">
    <despachos>
      <despacho codigo="IPAS158" nome="Concessão de registro"/>
    </despachos>
    <titulares>
      <titular nome-razao-social="DISTRIBUIDORA DE SUPERGELADOS REGIONAIS LTDA" pais="BR" uf="SP"/>
    </titulares>
    <marca apresentacao="Mista" natureza="De Serviço">
      <nome>DSR DISTRIBUIDORA DE SUPERGELADOS REGIONAIS</nome>
    </marca>
    <classes-vienna edicao="4">
      <classe-vienna codigo="24.1.15"/>
      <classe-vienna codigo="27.5.1"/>
    </classes-vienna>
    <lista-classe-nice>
      <classe-nice codigo="35">
        <especificacao>Administração de negócios, comercialização através de qualquer meio de produtos alimentícios, em especial, picolé, sorvetes, gelados comestíveis, sobremesas congeladas; franchising; representação comercial; serviços de distribuição, representação, importação e exportação de produtos alimentícios, em especial, picolé, sorvetes, gelados comestíveis, sobremesas congeladas; assessoria em gestão comercial ou industrial.; </especificacao>
        <status>Deferido</status>
      </classe-nice>
    </lista-classe-nice>
    <procurador>Vaz e Dias Advogados &amp; Associados</procurador>
  </processo>
  <processo numero="826455069" data-deposito="12/03/2004" data-concessao="14/01/2020" data-vigencia="14/01/2030">
    <despachos>
      <despacho codigo="IPAS158" nome="Concessão de registro"/>
    </despachos>
    <titulares>
      <titular nome-razao-social="ESCOLA CASINHA BRANCA DE UBERLÂNDIA LTDA-ME" pais="BR" uf="MG"/>
    </titulares>
    <marca apresentacao="Mista" natureza="De Serviço">
      <nome>CASINHA BRANCA</nome>
    </marca>
    <classes-vienna edicao="4">
      <classe-vienna codigo="7.1.8"/>
      <classe-vienna codigo="27.5.1"/>
    </classes-vienna>
    <lista-classe-nice>
      <classe-nice codigo="41">
        <especificacao>escola maternal, jardim e pré escola (ensino infantil).; </especificacao>
        <status>Deferido</status>
      </classe-nice>
    </lista-classe-nice>
    <procurador>CIDWAN UBERLÂNDIA LTDA ME</procurador>
 </revista> ```

The Highlighted areas is the data I want to get

The Highlighted areas are the data I want to get

So, Here's my code:

xtree = et.parse("/content/drive/My Drive/data/INPI/RM2558.xml")
xroot = xtree.getroot()df_cols = ['Processo', 'Despacho', 'Titular', 'Marca', 'Procurador']
rows =[]
for node in xroot:
  processo = node.attrib.get('numero')
  despacho = node.find('despachos')
  titular = node.find('titulares')
  marca = node.find('nome')
  procurador = node.find('procurador')

  rows.append({'Processo':processo, 'Despacho':despacho, 'Titular':titular, 'Marca':marca,'Procurador':procurador})

rpi_df = pd.DataFrame(rows, columns= df_cols)

The head() command give me this:

     Processo   Despacho    Titular     Marca   Procurador
0   909359539   [[]]      [[]]         None           []
1   826455069   [[]]      [[]]         None           []
2   916823270   [[]]      [[]]         None           []
3   916625303   [[]]      [[]]         None           []
4   916626873   [[]]      [[]]         None           None  

The "Processo" is working fine, but "Despacho", "Titular" and "Procurador" are giving me this brackets, and "Marca" is not getting me the data, is all Null values.

I converted everything to strings to see what those brackets would become and got this

Processo    Despacho    Titular     Marca   Procurador
0   909359539   <Element 'despachos' at 0x7fb47f082b38>     <Element 'titulares' at 0x7fb47f08e1d8>     None    <Element 'procurador' at 0x7fb47f08e548>
1   826455069   <Element 'despachos' at 0x7fb47f08e5e8>     <Element 'titulares' at 0x7fb47f08e688>     None    <Element 'procurador' at 0x7fb47f08e9f8>
2   916823270   <Element 'despachos' at 0x7fb47f08ea98>     <Element 'titulares' at 0x7fb47f08eb38>     None    <Element 'procurador' at 0x7fb47f08eea8>
3   916625303   <Element 'despachos' at 0x7fb47f08ef48>     <Element 'titulares' at 0x7fb47f099048>     None    <Element 'procurador' at 0x7fb47f0994a8>
4   916626873   <Element 'despachos' at 0x7fb47f099548>     <Element 'titulares' at 0x7fb47f0995e8>     None    None

So I guess this are addresses of the data in xml file, is that right?

My next try was this:

df_cols = ['Processo', 'Despacho', 'Titular', 'Marca', 'Procurador']
rows =[]
for node in xroot:
  processo = node.attrib.get('numero')
  despacho = node.find('despachos').text if node.find('despachos') is not None else None
  titular = node.find('titulares').text if node.find('titulares') is not None else None
  marca = node.find('marca').text if node.find('marca') is not None else None
  procurador = node.find('procurador').text if node.find('procurador') is not None else None

  rows.append({'Processo':processo, 'Despacho':despacho, 'Titular':titular, 'Marca':marca, 'Procurador':procurador})

rpi_df = pd.DataFrame(rows, columns= df_cols)

And I got this

Processo       Despacho     Titular     Marca   Procurador
0   909359539   \n           \n         \n     Vaz e Dias Advogados & Associados
1   826455069   \n           \n         \n     CIDWAN UBERLÂNDIA LTDA ME
2   916823270   \n           \n         \n     Wettor - Bureau de Apoio Empresarial S/S Ltda. ME
3   916625303   \n           \n         \n     Lilian de Melo Silveira Advogados Associados S/C
4   916626873   \n           \n         \n     None

Now "Procurador" is also working" and I'm getting some data in "Marca", but what's up with "/n"? Nowhere in the xml file there's a string like this. What's going on?


Solution

  • Note: you forgot to close a section processo before the ending revista

    The problem is you didn't adapt the code to the structure of the xml file.

    You get a \n because node.find('despachos').text gives you the text contained in despachos. Yet, there is no real text in it, just \n followed by spaces. Pandas will display that as it is, without any parsing. You have to apply node.find('despachos').text.rstrip() to avoid that.

    Furthermore, in despachos, you have one child node called despacho, which is a closed tag so again there is not text. It has however two attributes codigo and nome that you could use as for processo. For example:

    node.find('despachos').find('despacho').attrib.get('nome')
    

    It finds the first node despacho within the first node despachos and then it extracts the attribute nome.

    I assumed you wanted something like that:

    import xml.etree.ElementTree as et
    import pandas as pd
    
    xtree = et.parse("test.xml")
    xroot = xtree.getroot()
    df_cols = ['Processo', 'Despacho', 'Titular', 'Marca', 'Procurador']
    rows = []
    for node in xroot:
        processo = node.attrib.get('numero')
        despacho = node.find('despachos').find('despacho').attrib.get('nome')
        titular = node.find('titulares').find('titular').attrib.get('nome-razao-social')
        marca = node.find('marca').find('nome').text
        procurador = node.find('procurador').text
        rows.append({'Processo':processo, 'Despacho':despacho, 'Titular':titular, 'Marca':marca, 'Procurador':procurador})
    
    pd.DataFrame(rows, columns= df_cols)
    
        Processo    Despacho    Titular Marca   Procurador
    0   909359539   Concessão de registro   DISTRIBUIDORA DE SUPERGELADOS REGIONAIS LTDA    DSR DISTRIBUIDORA DE SUPERGELADOS REGIONAIS Vaz e Dias Advogados & Associados
    1   826455069   Concessão de registro   ESCOLA CASINHA BRANCA DE UBERLÂNDIA LTDA-ME CASINHA BRANCA  CIDWAN UBERLÂNDIA LTDA ME