此问题的版本已经被问过,如这里和这里。但是,我仍然无法让它工作。我正在尝试将XML文档解析为数据框架。问题在于某些观测值中没有出现某些变量,因此我会因为行数不同而出现错误。我的数据看起来像这样:
这个问题特别关注
编辑: 这是备选的
library("xml2")
library("dplyr")
example <- read_xml(
'
<particDesc>
<person role="participant" sameAs="#P484" xml:id="EDcon250_S1">
<age value="3">35-49</age>
<sex value="1">male</sex>
<occupation>waiter</occupation>
<langKnowledge>
<langKnown level="L1" tag="ita"/>
</langKnowledge>
</person>
<person role="participant" sameAs="#P485" xml:id="EDcon250_S7">
<age value="0">unknown</age>
<sex value="2">female</sex>
<occupation>waitress</occupation>
<langKnowledge>
<langKnown level="L1" tag="ger-AT"/>
</langKnowledge>
</person>
<person role="participant" sameAs="#P465" xml:id="EDcon250_S2">
<age value="2">25-34</age>
<sex value="2">female</sex>
<langKnowledge>
<langKnown level="L1" tag="ger-AT"/>
<langKnown level="L1" tag="eng-US"/>
</langKnowledge>
</person>
</particDesc>
')
我正在使用Wickham的xml2
包来读取xml。我更喜欢使用这个包,但如果这是解决问题的最佳(或唯一)方法,我也可以使用XML
。无论如何,我的代码如下:
participants <- xml_find_all(example, './/person[@role = "participant"]')
extract_participants <- function(div){
id <- xml_attr(div, "id")
same_as <- xml_attr(div, "sameAs")
role <- xml_attr(div, "role")
age <- xml_find_all(div, ".//age") %>% xml_text()
sex <- xml_find_all(div, ".//sex") %>% xml_text()
occupation <- xml_find_all(div, ".//occupation") %>% xml_text()
data_frame(id, same_as,role, age, sex, occupation)
}
parts_ls <- lapply(participants, extract_participants)
participants_df <- do.call(rbind, parts_ls)
这个问题特别关注
occupation
变量(第三个人没有),但在我的实际数据中,也可能是其他变量之一。正如我所说,我看到这个问题之前已经被问过了,但我无法让任何建议起作用(可能是因为我没有完全理解解决方案)。最终,我希望在特定节点缺失时返回NAs(因此第三个人的occupation
变量将为NA
)。编辑: 这是备选的
XML
版本。library("XML")
library("magrittr")
example2 <- xmlParse(
'
<particDesc>
<person role="participant" sameAs="#P484" xml:id="EDcon250_S1">
<age value="3">35-49</age>
<sex value="1">male</sex>
<occupation>waiter</occupation>
<langKnowledge>
<langKnown level="L1" tag="ita"/>
</langKnowledge>
</person>
<person role="participant" sameAs="#P485" xml:id="EDcon250_S7">
<age value="0">unknown</age>
<sex value="2">female</sex>
<occupation>waitress</occupation>
<langKnowledge>
<langKnown level="L1" tag="ger-AT"/>
</langKnowledge>
</person>
<person role="participant" sameAs="#P465" xml:id="EDcon250_S2">
<age value="2">25-34</age>
<sex value="2">female</sex>
<langKnowledge>
<langKnown level="L1" tag="ger-AT"/>
<langKnown level="L1" tag="eng-US"/>
</langKnowledge>
</person>
</particDesc>
')
example_root <- xmlRoot(example2)
process <- function(x){
id <- xmlGetAttr(x, "id")
role <- xmlGetAttr(x, "role")
age <- getNodeSet(x, ".//age") %>% xmlSApply(xmlValue)
sex <- getNodeSet(x, ".//sex") %>% xmlSApply(xmlValue)
#occupation <- getNodeSet(x, ".//occupation") %>% xmlSApply(xmlValue)
data.frame(id = id,
role = role,
#occupation = occupation,
age = age,
sex = sex,
stringsAsFactors = FALSE)
}
ls <- xpathApply(example_root, "//person", process)
df <- do.call(rbind, ls)
只需取消注释occupation
即可查看问题。