Erro ao importar arquivo XML

Olá, comunidade,

Comecei a usar arquivos no formato XML recentemente e, por isso, talvez minha dúvida seja trivial. Estou fazendo ajustes em um pacote e estou com dificuldades em importar um arquivo no formato XML para o R. Ao tentar importar o arquivo ‘20220214_Pedidos_xml_2015.xml’ disponível aqui com o código abaixo:

library(xml2) 
dados <- xml2::read_xml(x = '20220206_Pedidos_xml_2015.xml', encoding = 'UTF-16LE') 

O console mostra a seguinte mensagem de erro:

Error in read_xml.character(x = "20220206_Pedidos_xml_2015.xml", encoding = "UTF-16LE") : 
  Start tag expected, '<' not found [4]

Uma coisa que me chamou a atenção foi o fato de o arquivo XML não conter aquela tag inicial que geralmente os arquivos nesse formato têm.
Ex: <?xml version="1.0" encoding="UTF-8"?>

Alguém já teve que lidar com esse erro no R?

obs: O nome do arquivo que estou tentando importar pode mudar de acordo com o dia em que ele é baixado, mas o conteúdo permanece o mesmo, já que são dados de 2015.

Abraços,
Igor

Olá, Igor.

A única solução que consegui pensar envolve arrumar o XML antes de tentar processá-lo com o pacote xml2. A principal correção necessária (fora adicionar a tag inicial) é remover os caracteres inválidos do tipo &#x00;.

library(magrittr)

# Corrigir arquivo
"~/Downloads/20220215_Pedidos_xml_2015.xml" %>%
  readr::read_file(locale = readr::locale(encoding = "UTF-16LE")) %>%
  stringr::str_replace_all("<Pedido ", "\n\t<Pedido ") %>%
  stringr::str_replace("</Pedidos>", "\n</Pedidos>") %>%
  stringr::str_remove_all("&#x[0-9A-F]{2};") %>% # Remover caracteres inválidos
  stringr::str_c('<?xml version="1.0" encoding="UTF-8"?>\n', .) %>%
  readr::write_file("~/Downloads/20220215_Pedidos_xml_2015.xml")

# Ler corretamente
xml2::read_xml("~/Downloads/20220215_Pedidos_xml_2015.xml")
#> {xml_document}
#> <Pedidos>
#>  [1] <Pedido IdPedido="1887837" ProtocoloPedido="23480010257201512" Esfera="F ...
#>  [2] <Pedido IdPedido="1887842" ProtocoloPedido="23480010258201559" Esfera="F ...
#>  [3] <Pedido IdPedido="1887846" ProtocoloPedido="23480010259201501" Esfera="F ...
#>  [4] <Pedido IdPedido="1887851" ProtocoloPedido="23480010260201528" Esfera="F ...
#>  [5] <Pedido IdPedido="1887855" ProtocoloPedido="23480010261201572" Esfera="F ...
#>  [6] <Pedido IdPedido="1887858" ProtocoloPedido="23480010262201517" Esfera="F ...
#>  [7] <Pedido IdPedido="1887862" ProtocoloPedido="23480010263201561" Esfera="F ...
#>  [8] <Pedido IdPedido="1887869" ProtocoloPedido="23480010264201514" Esfera="F ...
#>  [9] <Pedido IdPedido="1887876" ProtocoloPedido="23480010265201551" Esfera="F ...
#> [10] <Pedido IdPedido="1887882" ProtocoloPedido="80200000438201565" Esfera="F ...
#> [11] <Pedido IdPedido="1887894" ProtocoloPedido="23480010266201503" Esfera="F ...
#> [12] <Pedido IdPedido="1887900" ProtocoloPedido="23480010267201540" Esfera="F ...
#> [13] <Pedido IdPedido="1887902" ProtocoloPedido="23480010268201594" Esfera="F ...
#> [14] <Pedido IdPedido="1887909" ProtocoloPedido="23480010269201539" Esfera="F ...
#> [15] <Pedido IdPedido="1887914" ProtocoloPedido="23480010270201563" Esfera="F ...
#> [16] <Pedido IdPedido="1887925" ProtocoloPedido="23480010271201516" Esfera="F ...
#> [17] <Pedido IdPedido="1887930" ProtocoloPedido="23480010272201552" Esfera="F ...
#> [18] <Pedido IdPedido="1887935" ProtocoloPedido="23480010273201505" Esfera="F ...
#> [19] <Pedido IdPedido="1887938" ProtocoloPedido="23480010274201541" Esfera="F ...
#> [20] <Pedido IdPedido="1887942" ProtocoloPedido="23480010275201596" Esfera="F ...
#> ...

Created on 2022-02-15 by the reprex package (v2.0.1)

Opa, Caio,
Funcionou perfeitamente. Valeu mesmo. Muito obrigado por toda a ajuda!

Caio, é possível abrir esse arquivo xml que foi gerado como um data frame no R? Eu vi que existem algumas funções específicas para isso, mas não encontrei uma no pacote xlm2. Qual seria a mais recomendada para que cada atributo dentro da tag Pedido seja uma coluna no dataframe?

Você pode usar a função xml2::xml_attrs() para pegar todos os atributos de uma tag e converter isso para um data frame:

library(magrittr)

# Converter em data frame
"~/Downloads/20220216_Pedidos_xml_2015.xml" %>%
  xml2::read_xml() %>%
  xml2::xml_find_all("//Pedido") %>%
  purrr::map(xml2::xml_attrs) %>%
  purrr::map_dfr(tibble::as_tibble_row)
#> # A tibble: 71,364 × 21
#>    IdPedido ProtocoloPedido   Esfera  Orgaodestinatario    Situacao DataRegistro
#>    <chr>    <chr>             <chr>   <chr>                <chr>    <chr>       
#>  1 1887837  23480010257201512 Federal UFPel – Fundação Un… Concluí… 01/07/2015  
#>  2 1887842  23480010258201559 Federal UFRGS – Universidad… Concluí… 01/07/2015  
#>  3 1887846  23480010259201501 Federal IFPI – Instituto Fe… Concluí… 01/07/2015  
#>  4 1887851  23480010260201528 Federal UFCG – Universidade… Concluí… 01/07/2015  
#>  5 1887855  23480010261201572 Federal UFF – Universidade … Concluí… 01/07/2015  
#>  6 1887858  23480010262201517 Federal UNIRIO – Universida… Concluí… 01/07/2015  
#>  7 1887862  23480010263201561 Federal IFRN – Instituto Fe… Concluí… 01/07/2015  
#>  8 1887869  23480010264201514 Federal UFAL – Universidade… Concluí… 01/07/2015  
#>  9 1887876  23480010265201551 Federal UFPel – Fundação Un… Concluí… 01/07/2015  
#> 10 1887882  80200000438201565 Federal MDR - Ministério do… Concluí… 01/07/2015  
#> # … with 71,354 more rows, and 15 more variables: ResumoSolicitacao <chr>,
#> #   DetalhamentoSolicitacao <chr>, PrazoAtendimento <chr>, FoiProrrogado <chr>,
#> #   FoiReencaminhado <chr>, FormaResposta <chr>, OrigemSolicitacao <chr>,
#> #   IdSolicitante <chr>, AssuntoPedido <chr>, Tag <chr>, DataResposta <chr>,
#> #   Resposta <chr>, Decisao <chr>, EspecificacaoDecisao <chr>,
#> #   SubAssuntoPedido <chr>

Created on 2022-02-16 by the reprex package (v2.0.1)

2 curtidas

Muito obrigado, Caio!

Oi, Caio,

Desculpe pelo abuso. Eu usei o código que você fez e funcionou para todos os anos, com exceção de 2020, que retornou a mensagem

Error: Invalid multibyte sequence

O problema parece estar na primeira linha que faz a leitura do arquivo:

readr::read_file(locale = readr::locale(encoding = "UTF-16LE"))

Pela pouca informação que encontrei sobre esse problema, me pareceu ser relacionado ao encoding do arquivo. Você tem ideia do que poderia ser? Obrigado mais uma vez.

Abs

Esse arquivo deve ter um encoding diferente. Você pode tentar trocar esse UTF-16LE por UTF-8 para ver se resolve; a função readr::guess_encoding() também pode ajudar a descobrir o encoding correto.

Opa, eu testei aqui e o read_file não funcionou com o ‘UTF-8’ e nem com um dos três encodings abaixo.

> readr::guess_encoding('20220218_Pedidos_xml_2020.xml')
# A tibble: 3 x 2
  encoding   confidence
  <chr>           <dbl>
1 UTF-16LE         1   
2 ISO-8859-1       0.68
3 ISO-8859-2       0.41

Você teria alguma outra sugestão?

Igor, não estou conseguindo reproduzir o seu problema. Aqui o código funcionou normalmente com os arquivos deste link: https://dadosabertos-download.cgu.gov.br/FalaBR/Arquivos_FalaBR_Filtrado/Arquivos_xml_2020.zip.

library(magrittr)

"~/Downloads/20220218_Pedidos_xml_2020.xml" %>%
  readr::read_file(locale = readr::locale(encoding = "UTF-16LE")) %>%
  stringr::str_replace_all("<Pedido ", "\n\t<Pedido ") %>%
  stringr::str_replace("</Pedidos>", "\n</Pedidos>") %>%
  stringr::str_remove_all("&#x[0-9A-F]{2};") %>% # Remover caracteres inválidos
  stringr::str_c('<?xml version="1.0" encoding="UTF-8"?>\n', .) %>%
  readr::write_file("~/Downloads/20220218_Pedidos_xml_2020.xml")

"~/Downloads/20220218_Pedidos_xml_2020.xml" %>%
  xml2::read_xml() %>%
  xml2::xml_find_all("//Pedido") %>%
  purrr::map(xml2::xml_attrs) %>%
  purrr::map_dfr(tibble::as_tibble_row)
#> # A tibble: 111,556 × 21
#>    IdPedido ProtocoloPedido   Esfera  Orgaodestinatario    Situacao DataRegistro
#>    <chr>    <chr>             <chr>   <chr>                <chr>    <chr>       
#>  1 951270   25072007838202063 Federal ANVISA – Agência Na… Concluí… 27/04/2020  
#>  2 1047582  23546023733202011 Federal UFV – Fundação Univ… Concluí… 25/05/2020  
#>  3 1206621  23546032056202013 Federal IFAM – Instituto Fe… Concluí… 08/07/2020  
#>  4 1214530  23546032551202022 Federal IFAM – Instituto Fe… Concluí… 10/07/2020  
#>  5 1308830  23546037540202039 Federal IFAM – Instituto Fe… Concluí… 13/08/2020  
#>  6 1316655  23546038101202043 Federal UFV – Fundação Univ… Concluí… 17/08/2020  
#>  7 1329393  08850005456202019 Federal DPRF – Departamento… Concluí… 21/08/2020  
#>  8 1435015  03006016040202063 Federal INMETRO – Instituto… Concluí… 27/08/2020  
#>  9 1435017  03006016030202028 Federal ME - Ministério da … Concluí… 27/08/2020  
#> 10 1435027  03006016028202059 Federal INMETRO – Instituto… Concluí… 27/08/2020  
#> # … with 111,546 more rows, and 15 more variables: ResumoSolicitacao <chr>,
#> #   DetalhamentoSolicitacao <chr>, PrazoAtendimento <chr>, FoiProrrogado <chr>,
#> #   FoiReencaminhado <chr>, FormaResposta <chr>, OrigemSolicitacao <chr>,
#> #   IdSolicitante <chr>, AssuntoPedido <chr>, Tag <chr>, DataResposta <chr>,
#> #   Resposta <chr>, Decisao <chr>, EspecificacaoDecisao <chr>,
#> #   SubAssuntoPedido <chr>

Created on 2022-02-18 by the reprex package (v2.0.1)

Caramba, que estranho. Eu peguei esse mesmo link, rodei o mesmo código e o erro ainda aparece.
O curioso é que o erro só ocorre com o arquivo de 2020.

> setwd('F:/Meu repositório/logo dail')
> library(magrittr)
> "20220218_Pedidos_xml_2020.xml" %>%
+   readr::read_file(locale = readr::locale(encoding = "UTF-16LE")) %>%
+   stringr::str_replace_all("<Pedido ", "\n\t<Pedido ") %>%
+   stringr::str_replace("</Pedidos>", "\n</Pedidos>") %>%
+   stringr::str_remove_all("&#x[0-9A-F]{2};") %>% # Remover caracteres inválidos
+   stringr::str_c('<?xml version="1.0" encoding="UTF-8"?>\n', .) %>%
+   readr::write_file("20220218_Pedidos_xml_2020.xml")
Error: Invalid multibyte sequence
> "20220218_Pedidos_xml_2020.xml" %>%
+   xml2::read_xml() %>%
+   xml2::xml_find_all("//Pedido") %>%
+   purrr::map(xml2::xml_attrs) %>%
+   purrr::map_dfr(tibble::as_tibble_row)
Error in read_xml.character(.) : 
  xmlParseCharRef: invalid xmlChar value 26 [9]