用于在R中展平复杂XML结构的递归函数

时间:2015-01-19 22:07:58

标签: xml r xpath

我在R中有许多需要XML处理的项目,而且我一直在努力。问题始终是一样的:将其他人的复杂XML结构解析为可行的数据帧。

下面我常见问题的例子。根据我使用的数据,节点名称在文件之间不一定是一致的,我通常只想在最深层次的水平上展平每个数据帧行,然后用成人节点名称或属性填充列。

想要从中得到:

library(XML)
# Small example extract
# Most data points removed

xml_extract <- xmlParse("
<COMPARISON ID=\"CMP-001\" NO=\"1\">
    <NAME>Incomplete resection (HGG)</NAME>
    <DICH_SUBGROUP CHI2=\"0.0\" CI_END=\"0.0\" CI_START=\"0.0\">
        <NAME>iMRI</NAME>
        <DICH_DATA CI_END=\"0.9640231041199472\" CI_START=\"0.017586933339032232\"/>
    </DICH_SUBGROUP>
    <DICH_SUBGROUP CHI2=\"0.0\" CI_END=\"0.0\" CI_START=\"0.0\">
        <NAME>5-ALA</NAME>
        <DICH_DATA CI_END=\"0.7124078544369572\" CI_START=\"0.4242461206130219\"/>
    </DICH_SUBGROUP>
    <DICH_SUBGROUP CHI2=\"0.0\" CI_END=\"0.0\" CI_START=\"0.0\">
        <NAME>DTI-neuronavigation</NAME>
        <DICH_DATA CI_END=\"0.6302184844574396\" CI_START=\"0.19776580326143214\"/>
    </DICH_SUBGROUP>
</COMPARISON>
")

对此:

dataframe

(我知道其中两列具有相同的NAME,这是问题的一部分。不是我的XML)。

我使用XML并查看XML2R。我很熟悉XPath。标准xmlToDataFrame类型命令不起作用。对于列表,标准Apply方法(例如xmlSApplyplyr)通常需要完全标准化的节点名称。

我正在寻找什么?一种递归函数,它贯穿并展平XML结构。我知道我已经方便地从表中的XML提取中省略了我不想要的位:)提前谢谢!


编辑以提供更复杂和典型的示例。

非常感谢你对此的帮助,尤其是hrbmstr。您的解决方案一直是我的方法。我有8000个文档,在示例中有很大的变化,因此正在寻找一个解决方案,其中变量名称由XML内容定义,而不是由函数定义。

复杂但典型的例子:

library(httr)
library(XML)
url = "http://onlinelibrary.wiley.com/doi/10.1002/14651858.CD007635.pub2/downloadstats"
response = POST(url, body = list("tAndCs" = TRUE))

xml_record = content(response, "parsed", type="text/xml")
path = "//ANALYSES_AND_DATA"
xml_extract = xml_record[[path]]

我有一个R interface for XSLT没有经验。也不是XSLT。

1 个答案:

答案 0 :(得分:2)

它只需要&#34;攻击&#34;系统地使用XML(不需要XSLT):

data.frame(comparison=xpathSApply(xml_extract, "//COMPARISON", xmlGetAttr, "ID"),
           name=xpathSApply(xml_extract, "//COMPARISON/NAME", xmlValue),
           dich_name=xpathSApply(xml_extract, "//COMPARISON/DICH_SUBGROUP/NAME", xmlValue),
           ci_end=xpathSApply(xml_extract, "//COMPARISON/DICH_SUBGROUP/DICH_DATA", xmlGetAttr, "CI_END"),
           ci_end=xpathSApply(xml_extract, "//COMPARISON/DICH_SUBGROUP/DICH_DATA", xmlGetAttr, "CI_START")
)

##   comparison                       name           dich_name             ci_end             ci_end.1
## 1    CMP-001 Incomplete resection (HGG)                iMRI 0.9640231041199472 0.017586933339032232
## 2    CMP-001 Incomplete resection (HGG)               5-ALA 0.7124078544369572   0.4242461206130219
## 3    CMP-001 Incomplete resection (HGG) DTI-neuronavigation 0.6302184844574396  0.19776580326143214

如果这不符合您的需求,请发布更复杂的XML示例。