我正试图使用tidyverse管道将XML转换为tibble。节点有attrs和文本。
输入。
txt <- c('<node attrA="1A" attrB="1B">text1</node>',
'<node attrA="2A" attrB="2B">text2</node>')
希望的输出(作为一个tibble)
~attrA, ~attrB, ~text,
1A, 1B, text1,
2A, 2B, text2
我可以得到xml_attr,使用这个方便的答案。tidyverse - 把命名的向量转换成data.frametibble的首选方法。
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,然后映射该函数,但我不能让它工作(与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"
我打赌可以做成我想要的tibble (虽然这不是我现在能做到的 :)
嗯,这似乎是工作,使用 .
synomyn来调用节点上的两个不同方法。
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)