2015-03-20 27 views
6

Ich habe eine Reihe von XML-Dateien und ein R-Skript, das ihren Inhalt in einen Datenrahmen liest. Allerdings habe ich jetzt Dateien, die ich wie gewohnt parsen wollte, aber es gibt etwas in ihrer Namespace-Definition, das es mir nicht erlaubt, ihre Werte normal mit XPath-Ausdrücken auszuwählen.Parsen von XML in R: Falsche Namespaces

XML-Dateien sind wie folgt aus:

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> 

Und die andere:

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> 

Die URL, Punkte xmlns ‚doesn t existieren.

Der R-Code ich verwende, ist wie folgt:

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 

Aber was ich als ein Ergebnis ist:

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

Wenn ich den Namespace-Link aus der zweiten Datei zu entfernen ich richtig :

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

natürlich könnte ich eine XSL müssen diese Namensräume von der ursprünglichen XML-Dateien zu entfernen, aber ich würde gerne t o habe eine Lösung, die innerhalb von R funktioniert. Gibt es eine Möglichkeit, R zu sagen, nur um alles in der XML-Deklaration zu ignorieren?

Antwort

3

Ich denke, es gibt keine einfache Möglichkeit, die Namespaces zu ignorieren. Der beste Weg ist, zu lernen, mit ihnen zu leben. Diese Antwort verwendet das neuere XML2-Paket. Gleiches gilt für die XML-Paketlösung.

Verwenden

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

Der erste Namensraum d1 zugeordnet ist. Wenn Sie XPath nicht finden, was Sie wollen, ist die wahrscheinlichste Ursache das Namespace-Problem.

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

Außerdem haben Sie diese im Pfad für jedes Element zu tun, damit das Tippen zu sparen, können Sie tun

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