2016-09-19 2 views
0

Ich habe einen sehr ähnlichen Fall zu diesem (Load XML to Dataframe in R with parent node attributes), wo ich versuche, XML in ein DF zu konvertieren, aber ich bin nicht in der Lage, mit dem nicht zu tun -existierende Knoten "sp" und "l". (Ich interessiere mich nicht für Knoten "m"). meine xml das sieht aus wie Angenommen:Umgang mit nicht vorhandenen Knoten in R xml zu Datenrahmen

<text> 
<body> 
<div1 type="scene1” n="1"> 
<sp who="fau"> 
    <l c="30" a="Settle thy studies"/> 
    <m x="40" b="To sound the depth of that thou wilt profess"/> 
</sp> 
<sp who="eang"> 
     <m x="105" b="Go forward, Faustus, in that famous art"/> 
</sp> 
</div1> 
<div1 type="scene2” n="2"> 
<sp who="fau"> 
    <l c="31" a="Settle thy"/> 
    <m x="50" b="To sound the depth of"/> 
</sp> 
<sp who="fau"> 
    <l c="32" a="Settle"/> 
    <m x="60" b="To sound the"/> 
</sp> 
<sp who="fau"> 
    <l c="33" a="Settle thy studies, Faustus"/> 
    <m x="40" b="To sound the depth of that thou wilt"/> 
</sp> 
</div1> 
<div1 type="scene3” n="3"> 
</div1> 
<div1 type="scene4” n="4"> 
</div1> 
<div1 type="scene5” n="5"> 
</div1> 
</body> 
</text> 

Das ist, was ich erhalten möchte:

n type  lc  la 
1 scene1 30  Settle thy studies 
2 scene2 31  Settle thy 
2 scene2 32  Settle 
2 scene2 33  Settle thy studies, Faustus 
3 scene3 NA  NA  
4 scene4 NA  NA 
5 scene5 NA  NA 

ich das versucht habe:

doc = xmlTreeParse("play.xml", useInternal = TRUE) 

bodyToDF <- function(x){ 
n <- xmlGetAttr(x, "n") 
type <- xmlGetAttr(x, "type") 
sp <- xpathApply(x, 'sp', function(sp) { 
if(is.null(sp)) { 
    lc <- NA 
    la <- NA 
} 
lc <- xpathSApply(sp, 'l', function(l) { xmlGetAttr(l,"c")}) 
la = xpathSApply(sp, 'l', function(l) { xmlValue(l,"a")}) 
data.frame(n, type, lc, la) 
}) 
do.call(rbind, sp) 
} 


res <- xpathApply(doc, '//div1', bodyToDF) 

aber es nicht funktioniert :

Error in data.frame(n, type, lc, la) : 
arguments imply differing number of rows: 1, 0 

und auch dies:

div1 = sapply(c("n","type"), function(x) xpathSApply(doc, "//div1", xmlGetAttr, x), simplify=FALSE) 

l = sapply(c("c","a"), function(x) xpathSApply(doc, "//l", xmlGetAttr, x), simplify=FALSE) 

df <- data.frame(div1,l) 

aber ich kann nicht scheinen, die richtige Abstimmung zwischen den Knoten und df Zeilen zu erhalten:

Error in data.frame(div1, l) : 
arguments imply differing number of rows: 5, 4 

Irgendwelche Ideen? Vielen Dank.

+0

Flicks Lösung kann helfen http://stackoverflow.com/questions/25346430/dealing-with-empty-xml-nodes-in-r –

+0

@ Hack-R Danke für den Zeiger, aber es auch nicht scheinen zu funktionieren: 'do.call (rbind, lapply (xmlChildren (xmlRoot (doc)), Funktion (x) { data.frame ( n = xmlGetNodeAttr (x," ./div1", "n", NA), type = xmlGetNodeAttr (x, "./div1","type",NA) lc = xmlGetNodeAttr (x," ./sp/l","c",NA), la = xmlGetNodeAttr (x, "./sp/l","a",NA) ) }))' 'n Typ lc la body.1 1 Szene1 NA N A body.2 2 scene2 NA NA body.3 3 scene3 NA NA body.4 4 scene4 NA NA body.5 5 scene5 NA NA' – cmvdi01

Antwort

0

Ihre eingefügten XML-Text hat Probleme (einige doppelte Anführungszeichen sind nicht schlicht doppelte Anführungszeichen), so ist hier eine gute Version davon für andere:

txt <- '<text> 
    <body> 
     <div1 type="scene1" n="1"> 
      <sp who="fau"> 
       <l c="30" a="Settle thy studies"/> 
       <m x="40" b="To sound the depth of that thou wilt profess"/> 
      </sp> 
      <sp who="eang"> 
       <m x="105" b="Go forward, Faustus, in that famous art"/> 
      </sp> 
     </div1> 
     <div1 type="scene2" n="2"> 
      <sp who="fau"> 
       <l c="31" a="Settle thy"/> 
       <m x="50" b="To sound the depth of"/> 
      </sp> 
      <sp who="fau"> 
       <l c="32" a="Settle"/> 
       <m x="60" b="To sound the"/> 
      </sp> 
      <sp who="fau"> 
       <l c="33" a="Settle thy studies, Faustus"/> 
       <m x="40" b="To sound the depth of that thou wilt"/> 
      </sp> 
     </div1> 
     <div1 type="scene3" n="3"></div1> 
     <div1 type="scene4" n="4"></div1> 
     <div1 type="scene5" n="5"></div1> 
    </body> 
</text>' 

Folgendes kann zurück zu XML Syntax, wenn wirklich notwendig übersetzt werden , aber die Idee, ähnlich wie in anderen Antworten ist, wo Sie jeden „Szene“ Knoten untersuchen müssen und die fehlenden Werte verwenden zu Fall behandeln, wenn sie auftritt:

library(xml2) 
library(purrr) 
library(dplyr) 

doc <- read_xml(txt) 

xml_find_all(doc, ".//*[contains(@type, 'scene')]") %>% 
    map_df(function(x) { 

    scene <- xml_attr(x, "type") 
    num <- xml_attr(x, "n") 

    lines <- xml_find_all(x, ".//l") 

    if (length(lines) == 0) { 
     data_frame(n=num, scene=scene, lc=NA, la=NA) 
    } else { 
     map_df(lines, function(y) { 
     lc <- xml_attr(y, "c") %||% NA 
     la <- xml_attr(y, "a") %||% NA 
     data_frame(n=num, scene=scene, lc=lc, la=la) 
     }) 
    } 

    }) 

und das gibt Ihnen Ihre gewünschte Ausgabe:

## # A tibble: 7 × 4 
##  n scene lc       la 
## <chr> <chr> <chr>      <chr> 
## 1  1 scene1 30   Settle thy studies 
## 2  2 scene2 31     Settle thy 
## 3  2 scene2 32      Settle 
## 4  2 scene2 33 Settle thy studies, Faustus 
## 5  3 scene3 <NA>      <NA> 
## 6  4 scene4 <NA>      <NA> 
## 7  5 scene5 <NA>      <NA> 
Verwandte Themen