在巨大的XML文件中组合值

时间:2014-03-25 18:43:27

标签: xml r

我需要在一些巨大的XML文件中找到并组合信息(doc< - xmlInternalTreeParse(file.name,useInternalNodes = TRUE,trim = TRUE)导致我的16GB计算机在完成之前开始交换到磁盘),并且遵循http://www.omegahat.org/RSXML/Overview.html上的好的指示。

从那里添加示例,这或多或少是我的文件的样子:

<?xml version="1.0" ?>
<TABLE>
  <SCHOOL>
    <NAME> School1 </NAME>
    <GRADES>
      <STUDENT> Fred </STUDENT>
      <TEST1> 66 </TEST1>
      <TEST2> 80 </TEST2>
      <FINAL> 70 </FINAL>
    </GRADES>
    <TEAMS>
      <SOCCER> SoccerTeam1 </SOCCER>
      <HOCKEY> HockeyTeam1 </HOCKEY>
    </TEAMS>
  </SCHOOL>
  <SCHOOL>
    <NAME> School2 </NAME>
    <GRADES>
      <STUDENT> Wilma </STUDENT>
      <TEST1> 97 </TEST1>
      <TEST2> 91 </TEST2>
      <FINAL> 98 </FINAL>
    </GRADES>
    <TEAMS>
      <SOCCER> SoccerTeam2 </SOCCER>
    </TEAMS>
  </SCHOOL>
</TABLE>

我需要为每个学校的学生列出曲棍球队和团队名称。示例中所需的输出应为“Fred”,“HockeyTeam1”,“School1”。真实的例子有成千上万的“学校”,“曲棍球队”和“球员”。

如何使用xmlEventParse解析文件以提取信息?我试图从文件中提取所有文本字段,但经过几个小时的等待后仍然没有输出。注意:真实文件比这更嵌套,因此不需要步骤固定级别来查找信息。

2 个答案:

答案 0 :(得分:8)

我们将使用XML包

library(XML)

并创建一个闭包,其中包含一个处理&#39; SCHOOL&#39; node,以及完成后检索结果的两个辅助函数。在每个SCHOOL节点上调用SCHOOL函数。如果找到曲棍球队,则使用/ SCHOOL / NAME / text()作为&#39;键和#SCHOOL / TEAMS / HOCKEY / text()和// STUDENT / text()(或/ SCHOOL / GRADES / STUDENT / text())作为值。每100个(默认情况下)有曲棍球队的学校会打印一条消息,以便有一些进度指示。 &#39;得到&#39;在事实之后使用函数来检索结果。

teams <- function(progress=1000) {
    res <- new.env(parent=emptyenv())   # for results
    it <- 0L                            # iterator -- nodes visited
    list(SCHOOL=function(elt) {
        ## handle 'SCHOOL' nodes 
        if (getNodeSet(elt, "not(/SCHOOL/TEAMS/HOCKEY)"))
            ## early exit -- no hockey team
            return(NULL)
        it <<- it + 1L
        if (it %% progress == 0L)
            message(it)
        school <- getNodeSet(elt, "string(/SCHOOL/NAME/text())") # 'key'
        res[[school]] <-
            list(team=getNodeSet(elt,
                   "normalize-space(/SCHOOL/TEAMS/HOCKEY/text())"),
                 students= xpathSApply(elt, "//STUDENT", xmlValue))
    }, getres = function() {
        ## retrieve the 'res' environment when done
        res
    }, get=function() {
        ## retrieve 'res' environment as data.frame
        school <- ls(res)
        team <- unlist(eapply(res, "[[", "team"), use.names=FALSE)
        student <- eapply(res, "[[", "students")
        len <- sapply(student, length)
        data.frame(school=rep(school, len), team=rep(team, len),
                   student=unlist(student, use.names=FALSE))
    })
}

我们使用函数

branches <- teams()
xmlEventParse("event.xml", handlers=NULL, branches=branches)
branches$get()

答案 1 :(得分:-2)

我认为您可以使用普通数据框。所以对此:

f=xmlParse('file.xml')
df=xmlToDataFrame(f)

然后你有一个数据框,为过滤对象制定一些条件。 或者,您想使用xml树,属性和值?

r=xmlRoot(f)

调出r或r [[1]] [[1]]之类的每个分支都会给你<NAME> School1 </NAME>