Combina valori in enormi file XML

Ho bisogno di trovare e combinare le informazioni in alcuni enormi file XML (doc <- xmlInternalTreeParse (file.name, useInternalNodes = TRUE, trim = TRUE) fa sì che il mio computer da 16 GB inizi a scambiare su disco prima di terminare) e ho seguito le buone istruzioni su http://www.omegahat.org/RSXML/Overview.html .

Aggiungendo all’esempio da lì, questo è più o meno come appare il mio file:

    School1    Fred   66   80   70     SoccerTeam1   HockeyTeam1      School2    Wilma   97   91   98     SoccerTeam2    

Devo elencare gli studenti per scuola con la squadra di hockey e i nomi delle squadre. L’output desiderato dell’esempio dovrebbe essere “Fred”, “HockeyTeam1”, “School1”. Il vero esempio ha migliaia di “scuole”, “squadre di hockey” e “giocatori”.

Come posso utilizzare xmlEventParse per analizzare i file per estrarre le informazioni? Ho provato ad estrarre tutti i campi di testo dai file, ma dopo ore di attesa non c’era ancora uscita. Nota: i file reali sono più nidificati di così, quindi non è sufficiente per fare passi sui livelli prefissati per trovare informazioni.

Useremo il pacchetto XML

 library(XML) 

e creare una chiusura che contenga una funzione per gestire il nodo ‘SCUOLA’, oltre a due funzioni di supporto per recuperare i risultati una volta terminato. La funzione SCUOLA viene invocata su ciascun nodo SCHOOL. Se trova una squadra di hockey, usa / SCHOOL / NAME / text () come “chiave” e / / SCHOOL / TEAM / HOCKEY / text () e // STUDENT / text () (o / SCHOOL / GRADES / STUDENT / text ()) come valori. Un messaggio viene stampato per ogni 100 (di default) scuole con squadre di hockey, in modo che ci sia qualche indicazione di progresso. La funzione ‘get’ viene utilizzata dopo il fatto per recuperare il risultato.

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

Usiamo la funzione come

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

Penso che tu possa lavorare con il normale data frame. Quindi per questo:

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

allora hai una cornice dati, crea alcune condizioni per filtrare gli oggetti. oppure, vuoi lavorare con l’albero xml, gli attributi e il valore?

 r=xmlRoot(f) 

chiama r o ogni ramo come r [[1]] [[1]] ti darà School1