从XML中提取嵌套数据作为R

时间:2016-01-30 17:30:38

标签: xml r xml-parsing xmlnodelist

我正在尝试从XML文件中提取数据,下面是示例结构:

<pwx creator="PerfPRO" version="1.0">
<workout>
<athlete></athlete>
<title></title>
<sportType>Bike</sportType>
<cmt></cmt>
<device id=""></device>
<time>2016-01-19T08:01:00</time>
<summarydata>
    <beginning>0</beginning>
    <duration>3600.012</duration>
</summarydata>
<segment>
    <summarydata>
        <beginning>0</beginning>
        <duration>120</duration>
    </summarydata>
</segment>
<segment>
    <summarydata>
        <beginning>120</beginning>
        <duration>120</duration>
    </summarydata>
</segment>
<segment>
    <summarydata>
        <beginning>240</beginning>
        <duration>120</duration>
    </summarydata>
</segment>

我想理想地将“段”块(开始和持续时间)中的数据作为数据帧访问。有许多段块。

我尝试过很多东西但似乎无法提取它,我得到的只是一个空列表。这是我所做的(pwx是文件名):

xmlData <- xmlInternalTreeParse(pwx, useInternalNodes = TRUE)
xmltop = xmlRoot(XMLdata)

d <- xpathSApply(doc = xmlData, path = "//pwx/workout/segment/summarydata/beginning", fun = xmlValue)

我似乎也可以通过以下方式访问所有细分:

segment <- xmltop[[1]]["segment"]

但似乎无法获得价值。我在上面尝试了很多变化。

非常感谢任何帮助,谢谢。

中号

编辑:

> summary(xmlData)
$nameCounts

    cad        dist          hr         pwr      sample         spd  timeoffset   beginning 
   3274        3274        3274        3274        3274        3274        3274          16 


duration summarydata     segment     athlete         cmt      device        make       model 
         16          16          15           1           1           1           1           1 
       name         pwx   sportType        time       title     workout 
          1           1           1           1           1           1 

$numNodes
[1] 22992

3 个答案:

答案 0 :(得分:4)

以下是一些原始的xml2处理,其中引入了一点purrr

library(xml2)
library(purrr)

nodes <- xml_find_all(doc, ".//segment/summarydata")

map_df(nodes, function(x) {
  kids <- xml_children(x)
  setNames(as.list(type.convert(xml_text(kids))), xml_name(kids))
})

## Source: local data frame [3 x 2]
## 
##   beginning duration
##       (int)    (int)
## 1         0      120
## 2       120      120
## 3       240      120

答案 1 :(得分:3)

您应该查看rvest。以下可能不是最优雅的使用方式,但它有效。

some_xml <- paste0(your_xml,'</workout></pwx>') # your example plus end of data to complete

library('rvest')
some_xml %>% read_xml %>% xml_nodes('summarydata')  -> nodes
nodes %>% xml_nodes('beginning') %>% xml_text -> beginning
nodes %>% xml_nodes('duration') %>% xml_text -> duration
data.frame(beginning, duration, stringsAsFactors = FALSE)
#   beginning duration
# 1         0 3600.012
# 2         0      120
# 3       120      120
# 4       240      120

答案 2 :(得分:0)

感谢所有回复并提供答案的人。我无法得到建议的答案,因为他们在上面(可能是我自己的失败)。

为了完整性和参考,我设法让这个工作:

pwx <- "myfile.pwx"
xmlData <- xmlInternalTreeParse(pwx, useInternalNodes = TRUE)
xmltop = xmlRoot(xmlData)
nodes <- getNodeSet(xmltop, '//as:summarydata', namespaces = c(as=xmlNamespace(xmltop)))
df <-xmlToDataFrame(nodes)

输出:

     beginning duration
1          0 3600.012
2          0      120
3        120      120
4        240      120
5        360      120
6        480      600
7       1080      180
8       1260      300
9       1560      300
10      1860      180
11      2040      300
12      2340      300
13      2640      180
14      2820      300
15      3120      300
16      3420  180.015

谢谢,

中号