R: xmlEventParse with Large, Varying-node XML Input and Conversion to Data Frame

时光总嘲笑我的痴心妄想 提交于 2019-12-01 14:37:20

Setup a function that will create a temp storage area for our element data as well as a function that will be called every time a is found.

library(XML)

uid_traverse <- function() {

  # we'll store them as character vectors and then make a data frame out of them.
  # this is likely one of the cheapest & fastest methods despite growing a vector
  # inch by inch. You can pre-allocate space and modify this idiom accordingly
  # for another speedup.

  uids <- c() 
  refs <- c()

  REC <- function(x) {

    uid <- xpathSApply(x, "//UID", xmlValue)
    ref <- xpathSApply(x, "//reference/uid", xmlValue)

    if (length(uid) > 0) {

      if (length(ref) == 0) {

        uids <<- c(uids, uid)
        refs <<- c(refs, NA_character_)

      } else {

        uids <<- c(uids, rep(uid, length(ref)))
        refs <<- c(refs, ref)

      } 

    } 

  }

  # we return a named list with the element handler and another
  # function that turns the vectors into a data frame

  list(
    REC = REC, 
    uid_df = function() { 
      data.frame(uid = uids, ref = refs, stringsAsFactors = FALSE)
    }
  )

}

We need one instance of this function.

uid_f <- uid_traverse()

Now, we call xmlEventParse() and give it our function, using invisible() since we don’t need what xmlEventParse() returns but just want the side-effects:

invisible(
  xmlEventParse(
  file = path.expand("~/data/so.xml"), 
  branches = uid_f["REC"])
)

And, we see the results:

uid_f$uid_df()
##       uid      ref
## 1 ABCD123 ABCD2345
## 2 ABCD123 ABCD3456
## 3 ABCD123 ABCD4567
## 4 XYZ0987     <NA>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!