R:如何最好地从节点中提取两个 XML 属性?

R: How to best extract two XML attributes from a node?

以下代码从 XML 文件中提取一个(或所有)属性:

library(xml2);library(magrittr);library(readr);library(tibble);library(knitr)   
fname<-'https://raw.githubusercontent.com/wardblonde/ODM-to-i2b2/master/odm/examples/CDISC_ODM_example_3.xml'
fname
x<-read_xml(fname)
xpath="//d1:ItemDef"
itemsNames <- x %>% xml_find_all(xpath, ns=xml_ns(x)) %>%  xml_attr('Name')
items <- x %>% xml_find_all(xpath, ns=xml_ns(x))

项目看起来像这样:

<ItemDef OID="IT.ABNORM" Name="Normal/Abnormal/Not Done" DataType="integer" Length="1" ...

示例文件可以在这里查看:https://raw.githubusercontent.com/wardblonde/ODM-to-i2b2/master/odm/examples/CDISC_ODM_example_3.xml

使用管道和 xml_attr,提取 NameDataType 属性并绑定它们的最佳方法是什么?

理想情况下,它将是一行超级高效的管道代码。我可以提取名称和类型并拥有 'data.frame(name=names,type=types)' 但这似乎不是最好和最现代的。

结果应该是带有列名和数据类型的小标题。

library(purrr)

map(items, xml_attrs) %>% 
  map_df(as.list) %>% 
  select(Name, DataType)
## # A tibble: 94 × 2
##                                   Name DataType
##                                  <chr>    <chr>
## 1             Normal/Abnormal/Not Done  integer
## 2          Actions taken re study drug     text
## 3                 Actions taken, other     text
## 4    Stop Day - Enter Two Digits 01-31     text
## 5                    Derived Stop Date     text
## 6  Stop Month - Enter Two Digits 01-12     text
## 7    Stop Year - Enter Four Digit Year     text
## 8                              Outcome     text
## 9           Relationship to study drug     text
## 10                            Severity     text
## # ... with 84 more rows

一个"base"版本:

lapply(items, xml_attrs) %>% 
  lapply(function(x) as.data.frame(as.list(x))[,c("Name", "DataType")]) %>% 
  do.call(rbind, .) %>%
  tbl_df()

注意:^^ 的一个问题是,如果缺少 NameDataType,那么您就是 SOL。您可以通过以下方式缓解这种情况:

lapply(items, xml_attrs) %>% 
  lapply(function(x) as.data.frame(as.list(x))[,c("Name", "DataType")]) %>% 
  data.table::rbindlist(fill=TRUE) %>% 
  tbl_df()

或:

lapply(items, xml_attrs) %>% 
  lapply(function(x) as.data.frame(as.list(x))[,c("Name", "DataType")]) %>% 
  bind_rows() %>% 
  tbl_df()

如果你不喜欢 purrr