R中的XML解析 - 子节点属性的递归体面

Posted

技术标签:

【中文标题】R中的XML解析 - 子节点属性的递归体面【英文标题】:XML parsing in R - recursive decent on attributes of children nodes 【发布时间】:2014-12-11 17:34:22 【问题描述】:

我是 XML 解析的新手,并且学习过各种教程。现在,我正在尝试从 PsychInfo 数据库的搜索结果中解析 XML 文档。基本上,我想要的是将每篇文章的属性保存到可以轻松分析的数据框中。但是,我的 XML 文档有一个我不完全理解的嵌套结构。

这是我的具体问题。 根据 MR.FLICK 的建议编辑

我想访问 XML 文件中子节点的所有属性——例如,文章标题 (btl)、发布日期 (pubinfo)、作者 (au) 等。当我应用函数 @987654322 @ 到根节点,它只返回一项。正如 MrFlick 在评论中所建议的那样,我需要设置某种形式的递归下降来提取这些其他属性。然后将这些其他属性保存在数据框中。

下面提供的是我一直在使用的代码,然后是我希望实现的具体示例。

library(XML)
library(RCurl) 

read.url <- function(url, ...)
    tmpFile <- tempfile()
    download.file(url, destfile = tmpFile, method = "curl")
    url.data <- xmlParse(tmpFile, ... )
    return(url.data)
    

这是 Gist 上数据的完整路径。 (尝试使用 bit.ly 进行缩短会导致无法正确阅读。任何有关解决此次要问题的建议都会有所帮助!)

DF https://gist.githubusercontent.com/beperron/e75a17e653ed668211bd/raw/2c4c31e0200c080094353d318e8e0ee59dce60fa/PsychInfo")

以下代码首先检查它是否属于 XML 文档类。随后的代码提取根节点和子节点。

class(DF) #Check to see it is an XML document
RootNode <- xmlRoot(DF) #Obtain root node
ChildNodes <- xmlChildren(RootNode) #Obtain children of root

此代码检查根节点的第一个子节点:

pietyScale <- ChildNodes[[1]] 
xmlName(pietyScale)
xmlSize(pietyScale)
xmlAttrs(pietyScale)
xmlValue(pietyScale)
xmlChildren(pietyScale)
xmlAttrs(pietyScale) 

如前所述,xmlAttrs 仅返回一项,即 resultID。我需要的信息嵌套在每个孩子中。我正在寻求基于以下标签提取的数据框:rec resultID、btl、jtl、pubinfo、doi。我想提取更多信息,但这肯定足以让我朝着正确的方向前进。

ID            1     
title         "Development and evaluation of the Arabic Filial Piety Scale"
journal       "Research on Social Work Practice"  
pubdate       "2010-07-01" 
doi           "10.1177/1049731510369495"

【问题讨论】:

正如所写的这个问题似乎过于广泛。目前还不清楚你的问题到底是什么。 pietyScale 节点是第一个 &lt;rec&gt; 节点,它只有一个属性 (resultID="1")。如果您还想提取子节点的所有属性,则必须设置某种形式的递归下降。 xmlAttrs 仅访问您作为参数传递的特定节点的属性。也许创建一个较小的示例输入并给出您想要的显式输出会有所帮助。 @MrFlick 感谢您的评论。我将按照您的建议编辑我的问题... 【参考方案1】:

在这个特定的文档中,您访问的是元素文本,而不是属性。我认为不需要“递归下降”。

这似乎产生了你正在寻找的东西:

get.data <- function(id) 
  tags <- c("bkinfo","jinfo","dt","artinfo/ui")
  data <- sapply(tags,function(tag)
    nodes <- DF[paste(sprintf("//rec[@resultID=%s]",id),tag,sep="//")]
    if (length(nodes)>0) xmlValue(nodes[[1]]) else NA
  )
  c(id,data)

ids    <- unlist(DF["//rec/@resultID"])
result <- as.data.frame(t(sapply(ids,get.data)),row.names=NA)
colnames(result) <- c("ID","title","journal","pubdate","doi")
t(result[1,])
#         1                                                             
# ID      "1"                                                           
# title   "Development and evaluation of the Arabic Filial Piety Scale."
# journal "Research on Social Work Practice1049731515527581"            
# pubdate "20100701"                                                    
# doi     "10.1177/1049731510369495"

所以这里的result 是一个数据框,每个 ID 为一行,每个数据(ID、标题等)为一列。您需要将数据从字符转换为任何合适的类。

需要注意的一点是,并非每个 resultID 都存在所有这些数据(例如 doi 字段有时会丢失)。因此,我们需要在尝试提取 xmlValue 之前检查节点集是否存在。

【讨论】:

以上是关于R中的XML解析 - 子节点属性的递归体面的主要内容,如果未能解决你的问题,请参考以下文章

dom4j递归解析XML字符串所有子节点

java获取XML指定节点的全部子节点

怎样获取xml中当前节点的直接孩子节点个数

GroovyXml 反序列化 ( 使用 XmlParser 解析 Xml 文件 | 获取 Xml 文件中的节点和属性 | 获取 Xml 文件中的节点属性 )

使用 BeautifulSoup 在 Python 中查找非递归 DOM 子节点

如何使用xsl根据属性将xml的兄弟节点更改为父节点和子节点