Home > Software engineering >  nested data from XML as tibble or Dataframe in R
nested data from XML as tibble or Dataframe in R

Time:11-26

I'm stuck at work with a code problem in R that I can't solve. I have the following XML Data:

<?xml version="1.0" encoding="utf-8"?>
<Votacion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://opendata.camara.cl/camaradiputados/v1">
  <Id>15446</Id>
  <Descripcion>Proyecto de Acuerdo N° 574</Descripcion>
  <Fecha>2012-06-13T14:47:29</Fecha>
  <TotalSi>12</TotalSi>
  <TotalNo>2</TotalNo>
  <TotalAbstencion>2</TotalAbstencion>
  <TotalDispensado>0</TotalDispensado>
  <Quorum Valor="1">Quórum Simple</Quorum>
  <Resultado Valor="2">Unánime</Resultado>
  <Tipo Valor="3">Proyecto de Acuerdo</Tipo>
  <Votos>
    <Voto>
      <Diputado>
        <Id>810</Id>
        <Nombre>Gabriel</Nombre>
        <ApellidoPaterno>Ascencio</ApellidoPaterno>
        <ApellidoMaterno>Mansilla</ApellidoMaterno>
      </Diputado>
      <OpcionVoto Valor="1">Afirmativo</OpcionVoto>
    </Voto>
    <Voto>
      <Diputado>
        <Id>855</Id>
        <Nombre>Carlos Abel</Nombre>
        <ApellidoPaterno>Jarpa</ApellidoPaterno>
        <ApellidoMaterno>Wevar</ApellidoMaterno>
      </Diputado>
      <OpcionVoto Valor="1">Afirmativo</OpcionVoto>
    </Voto>
    <Voto>
      <Diputado>
        <Id>862</Id>
        <Nombre>Pablo</Nombre>
        <ApellidoPaterno>Lorenzini</ApellidoPaterno>
        <ApellidoMaterno>Basso</ApellidoMaterno>
      </Diputado>
      <OpcionVoto Valor="0">En Contra</OpcionVoto>
    </Voto>
    <Voto>
      <Diputado>
        <Id>898</Id>
        <Nombre>Gabriel</Nombre>
        <ApellidoPaterno>Silber</ApellidoPaterno>
        <ApellidoMaterno>Romo</ApellidoMaterno>
      </Diputado>
      <OpcionVoto Valor="1">Afirmativo</OpcionVoto>
    </Voto>
  </Votos>
</Votacion>

I got the data from this api https://opendata.camara.cl/camaradiputados/WServices/WSLegislativo.asmx/retornarVotacionDetalle?prmVotacionId=15446

I want to process the data to obtain a tibble like this

Id Nombre ApellidoPaterno ApellidoMaterno OpcionVoto
810 Gabriel Acencio Mansilla Afirmativo
855 Abel Jarpa Webar Afirmativo
862 Pablo Lorenzini Basso En Contra

Any kind of help will be amazing, please !!!

CodePudding user response:

Something inspired by https://tidyr.tidyverse.org/articles/rectangle.html :

library(xml2)
library(dplyr)
library(tidyr)

read_xml(xml_str) %>% 
  xml_ns_strip() %>% 
  xml_find_all("//Voto") %>% 
  as_list() %>% 
  tibble(lst = .) %>% 

  # A tibble: 4 × 1

  unnest_wider(lst) %>% 

  # A tibble: 4 × 2
  # Diputado           OpcionVoto
  # 1 <named list [4]> <list [1]>

  unnest_wider("Diputado") %>% 

  # A tibble: 4 × 5
  #   Id         Nombre     ApellidoPaterno ApellidoMaterno OpcionVoto
  #   <list>     <list>     <list>          <list>          <list>    
  # 1 <list [1]> <list [1]> <list [1]>      <list [1]>      <list [1]>  

  unnest_longer(everything())
#> # A tibble: 4 × 5
#>   Id    Nombre      ApellidoPaterno ApellidoMaterno OpcionVoto
#>   <chr> <chr>       <chr>           <chr>           <chr>     
#> 1 810   Gabriel     Ascencio        Mansilla        Afirmativo
#> 2 855   Carlos Abel Jarpa           Wevar           Afirmativo
#> 3 862   Pablo       Lorenzini       Basso           En Contra 
#> 4 898   Gabriel     Silber          Romo            Afirmativo

Input:

xml_str <- 
'<?xml version="1.0" encoding="utf-8"?>
<Votacion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://opendata.camara.cl/camaradiputados/v1">
  <Id>15446</Id>
  <Descripcion>Proyecto de Acuerdo N° 574</Descripcion>
  <Fecha>2012-06-13T14:47:29</Fecha>
  <TotalSi>12</TotalSi>
  <TotalNo>2</TotalNo>
  <TotalAbstencion>2</TotalAbstencion>
  <TotalDispensado>0</TotalDispensado>
  <Quorum Valor="1">Quórum Simple</Quorum>
  <Resultado Valor="2">Unánime</Resultado>
  <Tipo Valor="3">Proyecto de Acuerdo</Tipo>
  <Votos>
    <Voto>
      <Diputado>
        <Id>810</Id>
        <Nombre>Gabriel</Nombre>
        <ApellidoPaterno>Ascencio</ApellidoPaterno>
        <ApellidoMaterno>Mansilla</ApellidoMaterno>
      </Diputado>
      <OpcionVoto Valor="1">Afirmativo</OpcionVoto>
    </Voto>
    <Voto>
      <Diputado>
        <Id>855</Id>
        <Nombre>Carlos Abel</Nombre>
        <ApellidoPaterno>Jarpa</ApellidoPaterno>
        <ApellidoMaterno>Wevar</ApellidoMaterno>
      </Diputado>
      <OpcionVoto Valor="1">Afirmativo</OpcionVoto>
    </Voto>
    <Voto>
      <Diputado>
        <Id>862</Id>
        <Nombre>Pablo</Nombre>
        <ApellidoPaterno>Lorenzini</ApellidoPaterno>
        <ApellidoMaterno>Basso</ApellidoMaterno>
      </Diputado>
      <OpcionVoto Valor="0">En Contra</OpcionVoto>
    </Voto>
    <Voto>
      <Diputado>
        <Id>898</Id>
        <Nombre>Gabriel</Nombre>
        <ApellidoPaterno>Silber</ApellidoPaterno>
        <ApellidoMaterno>Romo</ApellidoMaterno>
      </Diputado>
      <OpcionVoto Valor="1">Afirmativo</OpcionVoto>
    </Voto>
  </Votos>
</Votacion>'

Created on 2022-11-25 with reprex v2.0.2

CodePudding user response:

library(xml2)
library(purrr)

xml <- read_xml('<?xml version="1.0" encoding="utf-8"?>
<Votacion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://opendata.camara.cl/camaradiputados/v1">
  <Id>15446</Id>
  <Descripcion>Proyecto de Acuerdo N° 574</Descripcion>
  <Fecha>2012-06-13T14:47:29</Fecha>
  <TotalSi>12</TotalSi>
  <TotalNo>2</TotalNo>
  <TotalAbstencion>2</TotalAbstencion>
  <TotalDispensado>0</TotalDispensado>
  <Quorum Valor="1">Quórum Simple</Quorum>
  <Resultado Valor="2">Unánime</Resultado>
  <Tipo Valor="3">Proyecto de Acuerdo</Tipo>
  <Votos>
    <Voto>
      <Diputado>
        <Id>810</Id>
        <Nombre>Gabriel</Nombre>
        <ApellidoPaterno>Ascencio</ApellidoPaterno>
        <ApellidoMaterno>Mansilla</ApellidoMaterno>
      </Diputado>
      <OpcionVoto Valor="1">Afirmativo</OpcionVoto>
    </Voto>
    <Voto>
      <Diputado>
        <Id>855</Id>
        <Nombre>Carlos Abel</Nombre>
        <ApellidoPaterno>Jarpa</ApellidoPaterno>
        <ApellidoMaterno>Wevar</ApellidoMaterno>
      </Diputado>
      <OpcionVoto Valor="1">Afirmativo</OpcionVoto>
    </Voto>
    <Voto>
      <Diputado>
        <Id>862</Id>
        <Nombre>Pablo</Nombre>
        <ApellidoPaterno>Lorenzini</ApellidoPaterno>
        <ApellidoMaterno>Basso</ApellidoMaterno>
      </Diputado>
      <OpcionVoto Valor="0">En Contra</OpcionVoto>
    </Voto>
    <Voto>
      <Diputado>
        <Id>898</Id>
        <Nombre>Gabriel</Nombre>
        <ApellidoPaterno>Silber</ApellidoPaterno>
        <ApellidoMaterno>Romo</ApellidoMaterno>
      </Diputado>
      <OpcionVoto Valor="1">Afirmativo</OpcionVoto>
    </Voto>
  </Votos>
</Votacion>')

xml_ns(xml)
# d1  <-> http://opendata.camara.cl/camaradiputados/v1
# xsd <-> http://www.w3.org/2001/XMLSchema
# xsi <-> http://www.w3.org/2001/XMLSchema-instance


xml %>% xml_find_all(".//d1:Voto") %>% 
  map_dfr(~ set_names(
    c(.x %>% xml_child("d1:Diputado") %>% xml_children() %>% map(xml_text),
      .x %>% xml_child("d1:OpcionVoto") %>% xml_text()),
    c(.x %>% xml_child("d1:Diputado") %>% xml_children() %>% map(xml_name), "OpcionVoto")))

# A tibble: 4 × 5
#  Id    Nombre      ApellidoPaterno ApellidoMaterno OpcionVoto
#  <chr> <chr>       <chr>           <chr>           <chr>     
#1 810   Gabriel     Ascencio        Mansilla        Afirmativo
#2 855   Carlos Abel Jarpa           Wevar           Afirmativo
#3 862   Pablo       Lorenzini       Basso           En Contra 
#4 898   Gabriel     Silber          Romo            Afirmativo
  • Related