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

时间:2016-12-22 16:12:15

标签: r xml-parsing xml2

以下代码从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属性并将它们重新绑定的最佳方法是什么?

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

结果应该是列名和数据类型的结果。

1 个答案:

答案 0 :(得分:2)

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

一个&#34;基地&#34;版本:

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