首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在R中解析不规则XML

在R中解析不规则XML
EN

Stack Overflow用户
提问于 2013-08-30 17:50:56
回答 2查看 422关注 0票数 1

例如,如果我在R中加载了xml:

代码语言:javascript
复制
library(XML)
top <- newXMLNode("top")
tvp <- newXMLNode("TVP", parent = top)
time <- newXMLNode("time", "2012-01-01", parent = tvp)
value <- newXMLNode("value", "123", parent = tvp)
comment <- newXMLNode("comment",parent = tvp)
qualifer <-newXMLNode("qualifier", attrs = c(y = 'abc'), parent = comment)
commentText <-newXMLNode("info", attrs = c(y = 'something'), parent = comment)
tvp <- newXMLNode("TVP", parent = top)
time <- newXMLNode("time", "2012-01-02", parent = tvp)
value <- newXMLNode("value", "456", parent = tvp)
tvp <- newXMLNode("TVP", parent = top)
time <- newXMLNode("time", "2012-01-03", parent = tvp)
value <- newXMLNode("value", "789", parent = tvp)
comment <- newXMLNode("comment",parent = tvp)
newXMLNode("qualifier", attrs = c(y = 'efg'), parent = comment)
top

由此产生的XML:

代码语言:javascript
复制
<top>
  <TVP>
    <time>2012-01-01</time>
    <value>123</value>
    <comment>
      <qualifier y="abc"/>
      <info y="something"/>
    </comment>
  </TVP>
  <TVP>
    <time>2012-01-02</time>
    <value>456</value>
  </TVP>
  <TVP>
    <time>2012-01-03</time>
    <value>789</value>
    <comment>
      <qualifier y="efg"/>
    </comment>
  </TVP>
</top> 

我怎样才能得到正确的数据。包括限定符和信息属性吗?

这几乎是可行的,但并不完全是这样:

代码语言:javascript
复制
DF <- xmlToDataFrame(top,stringsAsFactors=FALSE)

结果如下:

代码语言:javascript
复制
        time value comment
1 2012-01-01   123        
2 2012-01-02   456    <NA>
3 2012-01-03   789   

我怎样才能得到:

我真正需要的是一种获取注释的子节点属性的方法:

代码语言:javascript
复制
        time value qualifer      info
1 2012-01-01   123      abc something
2 2012-01-02   456                   
3 2012-01-03   789      efg   
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-08-30 19:41:53

试试看以下几点。对于每个TVP,使用.//*[not(*)] xpath表达式查找所有子类叶,其中.表示从当前点开始,即在当前TVP节点,而//*意味着遍历所有后代,但[not(*)]将其限制在那些没有子节点的子类中。然后创建一个值列表(如果没有值,则创建属性),每个TVP创建一个列表组件。在最后一行中,它将每个列表组件转换为一个矩阵,并使用plyr的rbind.fill.matrix将矩阵放在一起:

代码语言:javascript
复制
xp <- xpathApply(top, "/top/TVP", xpathSApply, ".//*[not(*)]", function(x)
       setNames(ifelse(nzchar(xmlValue(x)), xmlValue(x), xmlAttrs(x)), xmlName(x)))
library(plyr)
do.call(rbind.fill.matrix, lapply(xp, t))

顺便说一句,在我的Windows系统(没有RStudio)上,您评论中的代码也崩溃了。

更新:小范围缩短解决方案

票数 1
EN

Stack Overflow用户

发布于 2013-08-30 19:04:29

尝试以下代码:

代码语言:javascript
复制
require(plyr) ### provides rbind.fill
getDataframe <- function(xml){
 out2 <- xmlSApply(xml,function(x){
 out <- xmlSApply(x, function(y){
  if(length(xmlChildren(y)) > 1){xmlSApply(y,xmlAttrs)
   }else{xmlValue(y)}})
  as.data.frame(t(unlist(out))) ## rbind.fill likes dataframes
  })
  return(do.call(rbind.fill,out2))
}
getDataframe(top)

这里的想法是:

  • 检查xml组件是否有子组件;然后使用xmlAttrs
  • 如果没有孩子使用xmlValue
  • 这给了我们一个列表,但是我们需要一个data.frame
  • 由于缺少一些值,我们需要来自plyr包的rbind.fill。
  • 最后,我们需要一些智能转换(as.data.frame)来使rbind.fill快乐。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18538772

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档