我有一个XML文档,如下所示:
<root>
<Item>
<A>text1</A>
<B>text2</B>
<C>text3</C>
<C>text4</C>
<C>text5</C>
<D>text6</D>
...
</Item>
<Item>
...
</Item>
...
</root>
有一个复杂因素,它相对简单:每个item
可以有任意数量的C
。
最终,我希望将其放在一个表中,例如:
A B C D
1 text1 text2 <list [3]> text6
我已经为其他变量创建了表格(可能是一种混乱的方式,但是它可以工作):
vnames<-c("A","B","D")
dat<-list()
for(i in 1:length(vnames)){
dat[[i]]<-xml_text(xml_find_first(nodeset,paste0(".//d1:",vnames[[i]]),xml_ns(xmlfile)))
}
dat<-as.data.frame(dat,col.names=vnames)
但是这种方法仅在xml_find_first
确实为您提供所需的一切时才有效。我可以使用xml_find_all
,但这会使列表长度对于合并而言是不相等的。我有一长串C
的清单,但我不知道哪一个附有哪个项目。
我当然可以遍历每个项目和xml_find_all
个C
,但这似乎效率很低。有没有更简单的方法可以做到这一点?
很抱歉是否已被问到;我找不到另外,我是XML的新手,因此可能需要一种全新的方法。谢谢!
答案 0 :(得分:1)
这是一个可能的解决方案,我不确定最终结果是否就是您想要的。
如果所有数据仅下一层,则此方法效果很好。如果数据在xml中向下存储了多个级别,则需要扩展此解决方案。基本方法是解析所有Item节点。从每个项目节点中的所有子节点收集信息,然后通过计算每个项目中的孩子数来创建项目索引。然后将所有数据存储在3列数据框中:ItemIndex,子名称和值。从这里开始,只需转换为所需的最终格式即可。
library(xml2)
page<-read_xml("<root>
<Item>
<A>text1</A>
<B>text2</B>
<C>text3</C>
<C>text4</C>
<C>text5</C>
<D>text6</D>
</Item>
<Item>
<A>text12</A>
<B>text22</B>
<C>text32</C>
</Item>
</root>")
#find all items and store as a list
items<-xml_find_all(page, ".//Item")
#extract all children's names and values
nodenames<-xml_name(xml_children(items))
contents<-trimws(xml_text(xml_children(items)))
#Need to create an index to associate the nodes/contents with each item
itemindex<-rep(1:length(items), times=sapply(items, function(x) {length(xml_children(x))}))
#store all information in data frame.
df<-data.frame(itemindex, nodenames, contents)
#Convert from long to wide format
library(tidyr)
pivot_wider(df, id_cols= itemindex, names_from = nodenames,
values_from = contents) # %>% unnest(cols = c(A, B, C, D))
# A tibble: 2 x 5
itemindex A B C D
<int> <list<fct>> <list<fct>> <list<fct>> <list<fct>>
1 [1] [1] [3] [1]
2 [1] [1] [1] [0]