2015-03-20 12 views
6

Mam kilka plików XML i skrypt R, który odczytuje ich zawartość do ramki danych. Jednak mam teraz pliki, które chciałem parsować jak zwykle, ale jest coś w ich definicji przestrzeni nazw, która nie pozwala mi wybrać ich wartości normalnie za pomocą wyrażeń XPath.Parsowanie XML w R: Nieprawidłowe przestrzenie nazw

pliki XML są tak:

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> 

A druga:

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> 

URL gdzie punkty xmlns się robi” t istnieje.

Kod R używam jest tak:

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 

Jednak to, co otrzymuję jako wynik to:

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

Jeśli usunąć link namespace z drugiego pliku uzyskać prawidłowe :

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

Oczywiście mogę mieć XSL, aby usunąć te przestrzenie nazw z oryginalnych plików XML, ale chciałbym t o jakieś rozwiązanie, które działa w ramach R. Czy jest jakiś sposób, aby powiedzieć R tylko zignorować wszystko w deklaracji XML?

Odpowiedz

3

Myślę, że nie ma łatwego sposobu na zignorowanie przestrzeni nazw. Najlepiej jest nauczyć się z nimi żyć. Ta odpowiedź będzie używać nowszego pakietu XML2. Ale to samo dotyczy rozwiązania pakietu XML.

Zastosowanie

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

Pierwszy nazw jest przypisany do d1. Jeśli XPath nie znajdzie tego, czego potrzebujesz, najbardziej prawdopodobną przyczyną jest problem z przestrzenią nazw.

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

Ponadto, trzeba to zrobić dla każdego elementu w ścieżce Tak, aby zapisać wpisując można zrobić

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