从XML提取数据框(文本),但文件在R中具有重复的节点名称

hgc7kmma  于 2023-02-14  发布在  其他
关注(0)|答案(1)|浏览(103)

我有一个XML文件,我正在使用它,并试图让输出看起来像您在R中使用xmlToDataFrame()函数时的样子。但是,我的文件太复杂,所以此函数不适合我,并给我错误,因为节点名称重复且不唯一。我附上了我的XML文件的简化版本,只是为了让您了解我想要实现什么

<HelloWorld created="2022-03-22" id="12we">
  <myname>omi</myname>
</HelloWorld>
<HelloWorld created="2022-03-12" id="18we">
  <myh>59</myh>
  <myfname>Tom</myfname>
  <mylname>John</mylname>
</HelloWorld>
<HelloWorld created="2022-03-30" id="188yye">
  <myh>60</myh>
  <favcolor>grey</favcolor>
  <myfname>Alex</myfname>
  <mylname>Tom</mylname>
</HelloWorld>

我希望由此生成以下输出
| 身份证|我的名字|迈赫|我的名字|我的名字|最喜欢的颜色|
| - ------|- ------|- ------|- ------|- ------|- ------|
| 12we|尾见|不适用|不适用|不适用|不适用|
| 18we|不适用|五十九|汤姆|约翰|不适用|
| 一八八年|不适用|六十|亚历克斯|汤姆|灰色|
我是XML新手,尝试了各种方法,但仍然没有运气正确提取数据。任何帮助都将不胜感激。

kjthegm6

kjthegm61#

# library(xml2)
xml <- xml2::read_html("quux.xml") |> xml2::as_list()

## either data.table or dplyr ...
out <- dplyr::bind_rows(xml$html$body)
out <- data.table::rbindlist(xml$html$body, use.names = TRUE, fill = TRUE)

out
# # A tibble: 3 × 5
#   myname    myh       myfname   mylname   favcolor 
#   <list>    <list>    <list>    <list>    <list>   
# 1 <chr [1]> <NULL>    <NULL>    <NULL>    <NULL>   
# 2 <NULL>    <chr [1]> <chr [1]> <chr [1]> <NULL>   
# 3 <NULL>    <chr [1]> <chr [1]> <chr [1]> <chr [1]>

由于xml的结构,所有的列都是列表列,因为我们习惯于所有元素的长度都是0或1,所以我们可以迭代所有元素来提取第一个:

out[] <- lapply(out, function(z) sapply(z, function(y) if (is.null(y)) NA else unlist(y)[1]))
out
# # A tibble: 3 × 5
#   myname myh   myfname mylname favcolor
#   <chr>  <chr> <chr>   <chr>   <chr>   
# 1 omi    NA    NA      NA      NA      
# 2 NA     59    Tom     John    NA      
# 3 NA     60    Alex    Tom     grey

数据:文件quux.xml,内容:

<HelloWorld created="2022-03-22" id="12we">
  <myname>omi</myname>
</HelloWorld>
<HelloWorld created="2022-03-12" id="18we">
  <myh>59</myh>
  <myfname>Tom</myfname>
  <mylname>John</mylname>
</HelloWorld>
<HelloWorld created="2022-03-30" id="188yye">
  <myh>60</myh>
  <favcolor>grey</favcolor>
  <myfname>Alex</myfname>
  <mylname>Tom</mylname>
</HelloWorld>

相关问题