lapply在xml对象列表上

时间:2016-05-12 11:39:16

标签: xml r subset lapply

这是我在这里的第一篇文章,所以请原谅发布指南中的任何错误

我试图从pubmed读取xml数据,以提取作者关联的数据

每个条目都包含一组节点,如下所示:

<AuthorList>
          <Author>
            <LastName>Serra-Blasco</LastName>
            <ForeName>Maria</ForeName>
            <Initials>M</Initials>
            <AffiliationInfo>
              <Affiliation>Department of Psychiatry, Hospital de la Santa Creu i Sant Pau, Biomedical Research Institute Sant Pau (IIB Sant Pau), Universitat Autònoma de Barcelona (UAB), Centro de Investigación Biomédica en Red de Salud Mental (CIBERSAM), Barcelona, Catalonia, Spain.</Affiliation>
            </AffiliationInfo>
          </Author>
          ...

我想最终得到一个包含每个作者姓名和联盟的数据框。

我尝试使用xpathSApply来解析读取&#34; //作者&#34;的节点,最后得到一个xml节点列表。

进一步解析被证明是一个问题:我编写的代码适用于此列表中的单个元素;

例如,如果列表是authorlist

我可以使用此函数(在元素中使用xpathSApply)为authorlist[[1]]提取适当的数组

但是当我尝试在这个函数周围进行lapply时,它会给我一个错误,指出它无法在列表上执行xpathApply。确切的错误调用是:

  

UseMethod中的错误(&#34; xpathApply&#34;):没有适用的方法   &#39; xpathApply&#39;应用于类&#34;列表&#34;

的对象

我猜测lapply用等价的[i]调用列表子集,而我需要的是[[i]]。有没有解决的办法?或者我是否还要考虑其他一些规则?

我可以改写(这只是我正在做的一些事情)但这个问题似乎很有意思,希望你能帮忙!

2 个答案:

答案 0 :(得分:2)

在使用html / xml文件时,我更喜欢使用rvest包。基于您的简单示例:

library(rvest)
myxml<-read_xml("author.xml")

lastname<-xml_text(xml_nodes(myxml,"LastName"))
firstname<-xml_text(xml_nodes(myxml,"ForeName"))
affiliation<-xml_text(xml_nodes(myxml,"Affiliation"))
df<-data.frame(firstname, lastname, affiliation)

如果xml文件的结构发生更改,则调用data.frame命令将出错,并且需要一些额外的工作来正确解析文件。

答案 1 :(得分:2)

显示产生错误的代码会有所帮助,但您可以尝试xmlToDataFrame

url <- "http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&id=23620451&rettype=XML"
doc <- xmlParse(url)

xmlToDataFrame(doc["//Author"])
           LastName ForeName Initials                   AffiliationInfo
1      Serra-Blasco    Maria        M Department of Psychiatry...Spain.
2          Portella  Maria J       MJ                              <NA>
3       Gómez-Ansón  Beatriz        B                              <NA>
...

如果你得到的节点有零个或多个标签,我通常会创建一个函数来将缺失的标签设置为NA,并使用一个分隔符来连接多个标签。

authors <- getNodeSet(doc, "//Author")

xpath2 <-function(x, path){
     y <- xpathSApply(x, path, xmlValue)
     ifelse(length(y)==0, NA, 
        ifelse(length(y)>1, paste(y, collapse=", "), y))
}

last <- sapply(authors, xpath2, ".//LastName")
aff <- sapply(authors, xpath2, ".//Affiliation")
data.frame(last, aff)
               last                               aff
1      Serra-Blasco Department of Psychiatry...Spain.
2          Portella                              <NA>
3       Gómez-Ansón                              <NA>