2016-10-16 4 views
0

мне нужно извлечь некоторые данные из XML, который выглядит следующим образом (упрощенный для краткости)извлечения данных из XML в R

<Doc name="Doc1"> 
    <Lists Count="1"> 
     <List Name="List1"> 
      <Points Count="3"> 
       <Point Id="1"> 
        <Tags Count ="1">"a"</Tags> 
        <Point Position="1" /> 
       </Point> 
       <Point Id="2"> 
        <Point Position="2" /> 
       </Point> 
       <Point Id="3"> 
        <Tags Count="1">"c"</Tags> 
        <Point Position="3" /> 
       </Point> 
      </Points> 
     </List> 
    </Lists> 
</Doc> 

Выходной сигнал должен быть кадр данных, который соответствует тег и положение для каждой точки Id

Point Tag Position 
1  1 a  1 
2  2 <NA>  2 
3  3 c  3 

Я новичок в XML, я играл с пакетом xml2. До сих пор я мог извлекать каждую переменную отдельно, но поскольку некоторые точки могут не иметь данных тега, я не могу найти способ сопоставить эти три параметра.

> library(xml2) 
> xml_data<-read_xml(...) 
> xml_data %>% xml_find_all("//Point") %>% xml_attr("Id") 
[1] "1" "2" "3" 
> xml_data %>% xml_find_all("//Vertical") %>% xml_attr("Position") 
[1] "1" "2" "3" 
> xml_data %>% xml_find_all("//Tags") %>% xml_text() 
[1] "\"a\"" "\"c\"" 

ответ

3

purrr и xml2 идут хорошо вместе :

library(xml2) 
library(purrr) 

txt <- '<Doc name="Doc1"> 
    <Lists Count="1"> 
     <List Name="List1"> 
      <Points Count="3"> 
       <Point Id="1"> 
        <Tags Count ="1">"a"</Tags> 
        <Point Position="1" /> 
       </Point> 
       <Point Id="2"> 
        <Point Position="2" /> 
       </Point> 
       <Point Id="3"> 
        <Tags Count="1">"c"</Tags> 
        <Point Position="3" /> 
       </Point> 
      </Points> 
     </List> 
    </Lists> 
</Doc>' 

doc <- read_xml(txt) 
xml_find_all(doc, ".//Points/Point") %>% 
    map_df(function(x) { 
    list(
     Point=xml_attr(x, "Id"), 
     Tag=xml_find_first(x, ".//Tags") %>% xml_text() %>% gsub('^"|"$', "", .), 
     Position=xml_find_first(x, ".//Point") %>% xml_attr("Position") 
    ) 
    }) 
## # A tibble: 3 × 3 
## Point Tag Position 
## <chr> <chr> <chr> 
## 1  1  a  1 
## 2  2 <NA>  2 
## 3  3  c  3 
1

Выполнить xpathApply над //Points/Point узлов и для каждого такого узла x получить Id, то Tag (или NA, если нет) и Position:

library(XML) 

doc <- xmlTreeParse(Lines, asText = TRUE, useInternalNodes = TRUE) 

do.call("rbind", xpathApply(doc, "//Points/Point", function(x) 
    data.frame(Id = as.numeric(xmlAttrs(x)[["Id"]]), 
      Tags = c(gsub('"', '', xmlValue(x[["Tags"]])), NA)[[1]], 
      Position = as.numeric(xmlAttrs(x[["Point"]])[["Position"]], 
      stringsAsFactors = FALSE)))) 

давая:

Id Tags Position 
1 1 a  1 
2 2 <NA>  2 
3 3 c  3 

изменение

Вариант выше сказанного дает тот же ответ. На каждом Point узле создает строку атрибутов и значений, а затем использует read.table, чтобы прочитать его в:

library(XML) 

doc <- xmlTreeParse(Lines, asText = TRUE, useInternalNodes = TRUE) 

xp <- xpathSApply(doc, "//Points/Point", function(x) paste(
     xmlAttrs(x)[["Id"]], 
     c(gsub('"', '', xmlValue(x[["Tags"]])), NA)[[1]], 
     xmlAttrs(x[["Point"]])[["Position"]])) 
read.table(text = xp, col.names = c("Id", "Tags", "Position"), as.is = TRUE) 

Примечание: Input Lines является:

Lines <- '<Doc name="Doc1"> 
    <Lists Count="1"> 
     <List Name="List1"> 
      <Points Count="3"> 
       <Point Id="1"> 
        <Tags Count ="1">"a"</Tags> 
        <Point Position="1" /> 
       </Point> 
       <Point Id="2"> 
        <Point Position="2" /> 
       </Point> 
       <Point Id="3"> 
        <Tags Count="1">"c"</Tags> 
        <Point Position="3" /> 
       </Point> 
      </Points> 
     </List> 
    </Lists> 
</Doc>'