Объедините значения в огромные XML-файлы

Мне нужно найти и объединить информацию в некоторых огромных XML-файлах (doc <- xmlInternalTreeParse (file.name, useInternalNodes = TRUE, trim = TRUE) приводит к тому, что мой компьютер на 16 ГБ начинает загружаться на диск перед завершением), и следовал хорошим инструкциям на 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 ответа

Решение

Мы будем использовать пакет XML

library(XML)

и создайте замыкание, которое содержит функцию для обработки узла 'SCHOOL', а также две вспомогательные функции для получения результатов по завершении. Функция SCHOOL вызывается на каждом узле SCHOOL. Если он находит хоккейную команду, он использует /SCHOOL/NAME/text() в качестве "ключа", а /SCHOOL/TEAMS/HOCKEY/text() и //STUDENT/text() (или /SCHOOL/GRADES/ СТУДЕНТ / текст ()) в качестве значений. Сообщение печатается для каждых 100 (по умолчанию) школ с хоккейными командами, так что есть некоторые признаки прогресса. Функция get используется после факта для получения результата.

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()

Я думаю, что вы можете работать с нормальным фреймом данных. Итак, для этого:

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

тогда у вас есть фрейм данных, установите некоторые условия для фильтрации объектов. или вы хотите работать с деревом xml, атрибутами и значением?

r=xmlRoot(f)

Вызовите r или любую ветвь наподобие r[[1]][[1]]. <NAME> School1 </NAME>

Другие вопросы по тегам