Получите xml_attrs и xml_text в конвейере tidyverse - PullRequest
1 голос
/ 10 апреля 2020

Я пытаюсь преобразовать XML в тиббл, используя конвейер Tidyverse. Узлы имеют и атрибуты, и текст.

Ввод:

txt <- c('<node attrA="1A" attrB="1B">text1</node>',
         '<node attrA="2A" attrB="2B">text2</node>')

Желаемый вывод (в виде таблицы)

~attrA, ~attrB, ~text,
1A, 1B, text1,
2A, 2B, text2

Я могу получить xml_attr, используя этот удобный ответ: tidyverse - предпочтительный способ превратить именованный вектор в data.frame / tibble

library(xml2)
library(tidyverse)

txt <- c('<node attrA="1A" attrB="1B">text1</node>',
         '<node attrA="2A" attrB="2B">text2</node>')

txt %>% 
  map(read_xml) %>% 
  map(xml_attrs) %>% 
  map_df(bind_rows) 

Но это не дает text1 и text2. Я могу получить только xml_text:

library(xml2)
library(tidyverse)

txt <- c('<node attrA="1A" attrB="1B">text1</node>',
         '<node attrA="2A" attrB="2B">text2</node>')

txt %>% 
  map(read_xml) %>%
  map(xml_text) %>%
  unlist() %>% 
  tibble(text = .)

Любая идея, как я могу объединить их, чтобы получить и xml_text и xml_attrs через один конвейер?

Я пытался написать функцию, чтобы взять узел xml и запустить на нем и xml_text, и xml_attrs, затем отобразив эту функцию, но я не смог заставить это работать (что-то связанное с externalptrs используется xml2?)

Мне кажется, я действительно задаю вопрос о «повторном использовании» вещи, переданной в конвейере, поэтому я предполагаю, что ответ связан с . в качестве псевдонима.

Редактировать: хммммм, возможно, as_list - это решение здесь (хотя мне все еще хотелось бы, чтобы элемент управления, вызываемый вызовами xml_attrs и xml_text.

txt %>% 
  map(read_xml) %>% 
  map(xml_find_all, xpath = "//node") %>% 
  map(as_list)

производит

[[1]]
[[1]][[1]]
[[1]][[1]][[1]]
[1] "text1"

attr(,"attrA")
[1] "1A"
attr(,"attrB")
[1] "1B"


[[2]]
[[2]][[1]]
[[2]][[1]][[1]]
[1] "text2"

attr(,"attrA")
[1] "2A"
attr(,"attrB")
[1] "2B"

, на которую я держу пари, можно превратить в нужный мне тиббл (хотя сейчас он мне не подходит:)

1 Ответ

1 голос
/ 10 апреля 2020

Ну, похоже, это работает, использует синомин . для вызова двух разных методов на узлах.

txt %>% 
  map(read_xml) %>% 
  map(xml_find_all, xpath = "//node") %>% 
  tibble(text = map_chr(., xml_text),
         # attr as a tibble column, pluck needed to unpack one
         # level of list.
         xml_attr_col = map(., xml_attrs) %>% map(pluck,1)) %>% 
  select(-1) %>%  # drop original node column somehow created by tibble
  # groovy function to unnest that tibble column
  unnest_wider(xml_attr_col)
...