xml2 - 更有效地从父节点获取信息

时间:2017-10-26 06:57:51

标签: r xml xml2

我有一个看起来像这样的xml:

...
<node id=1>
 <child>a</child>
 <child>b</child>
 <child>c</child>
</node>
<node id=2>
 <child>d</child>
 <child>e</child>
</node>
...

我正在寻找的是一个data.frame,指的是孩子的父母:

node_id  child_text
      1           a
      1           b
      1           c
      2           d
      2           e

我只能想到使用xml2的两种解决方案:

(a)使用xml_find_all(...)创建一组子节点,然后使用for循环来操纵xml结构以获取所需信息。显然非常低效。

(b)获取一组父节点和一组子节点。从父集中提取信息并计算每个父母拥有的子女数。然后使用rep(information,no_of_children)从上面填充node_id列。更好但仍然很愚蠢。

我认为必须有更有效的方法吗?我很高兴有任何建议,因为我现在使用这些方法已经超过一个月了,同时处理xigabites - 非常低效 - xml格式的数据结构。我也不仅限于使用xml2,也可以切换到另一种编程语言,如果这会大大提高性能。唯一重要的部分是我想从那里直接将数据加载到数据库中。

1 个答案:

答案 0 :(得分:0)

鉴于您提供的非常通用的示例,我将rvestpurrr一起使用:

x <- "<node id=1>
   <child>a</child>
   <child>b</child>
   <child>c</child>
  </node>
  <node id=2>
   <child>d</child>
   <child>e</child>
  </node>"


library(rvest)
library(purrr)

read_html(x) %>% 
  html_nodes('node') %>% 
  map_df(~{
    .x %>% 
      html_nodes('child') %>% 
      html_text() -> child
    data.frame(child = child, stringsAsFactors = FALSE)
  }, .id = 'node')

#>   node child
#> 1    1     a
#> 2    1     b
#> 3    1     c
#> 4    2     d
#> 5    2     e

与您的方法进行比较的一些基准:

rbenchmark::benchmark(read_html(xml) %>% 
                        html_nodes('node') %>% 
                        map_df(~{
                          .x %>% 
                            html_nodes('child') %>% 
                            html_text() -> child
                          data.frame(child = child, stringsAsFactors = FALSE)
                        }, .id = 'node'), columns = c('replications', 'elapsed', 'user.self'))
#>   replications elapsed user.self
#> 1          100   0.964     0.964