R 中的 XML:多个 Children 同名且无循环

XML in R: Multiple Children with Same Name without Loops

我有一个 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

最终,我希望在 table 中拥有它,例如:

  A     B     C          D    
1 text1 text2 <list [3]> text6

我已经为其他变量创建了 table(可能是一种混乱的方式,但它有效):

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 中向下存储多个级别,则需要扩展此解决方案。基本方法是将所有 Item 节点解析出来。从每个项目节点中收集所有子节点的信息,然后通过计算每个项目中的子节点数来创建项目索引。然后将所有数据存储在一个 3 列数据框中:ItemIndex、Child Name 和 value。从这里开始,就是转换为所需的最终格式。

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]