2015-03-20 11 views
6

Ho un sacco di file XML e uno script R che legge il loro contenuto in un frame di dati. Tuttavia, ho ottenuto ora i file che volevo analizzare come al solito, ma c'è qualcosa nella loro definizione del namespace che non mi permette di scegliere i loro valori normalmente con espressioni XPath.Analisi XML in R: spazi dei nomi errati

file XML sono come questo:

xml_nons.xml

<?xml version="1.0" encoding="UTF-8"?> 
<XML> 
    <Node> 
     <Name>Name 1</Name> 
     <Title>Title 1</Title> 
     <Date>2015</Date> 
    </Node> 
</XML> 

E l'altro:

xml_ns.xml

<?xml version="1.0" encoding="UTF-8"?> 
<XML xmlns="http://www.nonexistingsite.com"> 
    <Node> 
     <Name>Name 2</Name> 
     <Title>Title 2</Title> 
     <Date>2014</Date> 
    </Node> 
</XML> 

l'URL in cui xmlns punti per doesn' Esistono

Il codice R che uso è simile a questo:

library(XML) 

xmlfiles <- list.files(path = ".", 
         pattern="*.xml$", 
         full.names = TRUE, 
         recursive = TRUE) 

n <- length(xmlfiles) 
dat <- vector("list", n) 

for(i in 1:n){ 
     doc <- xmlTreeParse(xmlfiles[i], useInternalNodes = TRUE) 
     nodes <- getNodeSet(doc, "//XML") 
     x <- lapply(nodes, function(x){ data.frame(
       Filename = xmlfiles[i], 
       Name = xpathSApply(x, ".//Node/Name" , xmlValue), 
       Title = xpathSApply(x, ".//Node/Title" , xmlValue), 
       Date = xpathSApply(x, ".//Node/Date" , xmlValue) 
      )}) 
      dat[[i]] <- do.call("rbind", x) 
    } 

    xml <- do.call("rbind", dat) 
    xml 

Tuttavia, ciò che ottengo come risultato è:

Filename   Name Title Date 
./xml_nons.xml  Name 1 Title 1 2015 

Se rimuovo il link spazio dei nomi dal secondo file ottengo corretto :

Filename   Name Title Date 
./xml_nons_1.xml Name 1 Title 1 2015 
./xml_ns_1.xml  Name 2 Title 2 2014 

Naturalmente potrei avere un XSL per rimuovere tali spazi dei nomi da file XML originali, ma vorrei t o hai qualche soluzione che funzioni all'interno R. C'è un modo per dire a R solo di ignorare tutto nella dichiarazione XML?

risposta

3

Penso che non ci sia un modo semplice per ignorare i namespace. Il modo migliore è imparare a vivere con loro. Questa risposta utilizzerà il nuovo pacchetto XML2. Ma lo stesso vale per la soluzione del pacchetto XML.

Usa

library(XML2) 
fname='myfile.xml' 
doc <- read_xml(fname) 
#peak at the namespaces 
xml_ns(doc) 

Il primo spazio dei nomi è assegnato a d1. Se XPath non trova quello che vuoi, la causa più probabile è il problema dello spazio dei nomi.

xpath <- "//d1:FormDef" 
ns <- xml_find_all(doc,xpath, xml_ns(doc)) 
ns 

Inoltre, devi fare questo per ogni elemento nel percorso Quindi, per risparmiare digitazione, si può fare

library(stringr) 
> xpath <- "/ODM/Study" 
> (xpath<-str_replace_all(xpath,'/','/d1:')) 
[1] "/d1:ODM/d1:Study"