R - 将未对齐的XML属性解析为数据框

时间:2015-07-17 22:25:21

标签: xml r xml-parsing dataframe

我有一个具有这种结构的xml文件。

<?xml version="1.0" encoding="utf-8"?>
<b>
    <c name="Foo" stuff="89" attr="First line&#xA;Second line"/>
    <c name="Bar" ID="ontime" stuff="23" attr="Blahs"/>
    <c ID="delay" name="Dog"  newattr="Clahs"/>
    ...
</b>

正如您所看到的,属性非常混乱;缺少值和未对齐。我想将其转换为R语言中的以下数据框(或任何其他类似表格的结构)以供进一步分析。

╔══════════╦══════════════╦══════════════════════════════════╦════════════════╦═════════╗
║   name   ║ stuff        ║ attr                             ║ ID             ║ newattr ║
╠══════════╬══════════════╬══════════════════════════════════╬════════════════╬═════════╣
║ 1 Foo    ║  89          ║ "First line&#xA;Second line"     ║ NA             ║  NA     ║
║ 2 Bar    ║  23          ║ "Blahs"                          ║ "ontime"       ║  NA     ║
║ 3 Dog    ║  NA          ║      NA                          ║ "delay"        ║ "Clahs" ║
╚══════════╩══════════════╩══════════════════════════════════╩════════════════╩═════════╝

由于我有限的R和解析经验,我失败了。我有一种感觉xapplySApply可能有用,但无法弄清楚如何设置路径。

我想探索的另一种技术是让代码自己识别新属性。换句话说,代码中没有对属性的名称进行硬编码。例如,当它看到第3行时,它会自动将新列添加到数据框并将其命名为“newattr”。

非常感谢你的帮助。

------------------- 2015年7月18日新增---------------------- -

这是我的蛮力方法。我相当确定有更好的方法来做到这一点,因为它超级慢(在现代个人笔记本电脑上处理一个~250MB xml的6小时)。

myxmlToDataFrame2 <- function(file) {
  xL <- xmlToList(xmlParse(file))
  xL <- unname(xL)

  # initialize data frame
  df <- data.frame(t(xL[[1]]), stringsAsFactors = FALSE)

  number_of_attribute <- length(df)
  number_of_row <- length(xL)

  for (i in 2:number_of_row) {
    # examine each element in the new row
    for (j in 1:length(xL[[i]])) {
      df[i,attributes(xL[[i]])$names[j]] <- xL[[i]][[j]]    
    }
  }
  df
}

2 个答案:

答案 0 :(得分:0)

我们真的需要一个完整的例子。填写NA数据会有问题。

这是让你入门的东西:

library(XML)

xml <- '<b>
<c name="Foo" stuff="89" attr="First line&#xA;Second line"/>
<c name="Bar" ID="ontime" stuff="23" attr="Blahs"/>
<c ID="delay" name="Dog"  attr="Clahs"/>
</b>'

xml <- xmlParse(xml)

attr_vals <- unlist(xpathApply(xmlParse(xml), "//b/c/@attr"))
stuff_vals <- unlist(xpathApply(xmlParse(xml), "//b/c/@stuff"))
ids_vals <- unlist(xpathApply(xmlParse(xml), "//b/c/@ID"))

答案 1 :(得分:0)

您可以尝试在c节点上使用xmlAttrsToDataFrame

XML:::xmlAttrsToDataFrame(xml["//c"])
  name stuff                    attr     ID newattr
1  Foo    89 First line\nSecond line   <NA>    <NA>
2  Bar    23                   Blahs ontime    <NA>
3  Dog  <NA>                    <NA>  delay   Clahs