我试图将XML文档的树结构表示为路径列表或连接节点名称列表。例如:
<node id="A">
<node id = "AA">
<node id = "AAA"></node>
</node>
<node id = "AB">
</node>
<node id = "AC">
</node>
</node>
应转换为:
//A/AA/AAA
//A/AB
//A/AC
或者这个:
A, AA, AAA
A, AB
A, AC
我找到了其他语言的例子:
Get a list of all root-to-leaf paths in a DOM tree
但我不知道如何遍历R中的节点。我正在使用xml2包。
有没有人解决过这个问题?要求朋友。
答案 0 :(得分:1)
@alistaire在上述评论中提出的解决方案适用于此处。
请记住删除命名空间。
library( dplyr )
library( xml2 )
dat <- read_xml( "https://s3.amazonaws.com/irs-form-990/201541349349307794_public.xml" )
dat %>% xml_find_all( '//*') %>% xml_path()
# [1] "/*" "/*/*[1]"
# [3] "/*/*[1]/*[1]" "/*/*[1]/*[2]"
# [5] "/*/*[1]/*[3]" "/*/*[1]/*[3]/*[1]"
xml_ns_strip( dat )
dat %>% xml_find_all( '//*') %>% xml_path()
# [1] "/Return"
# [2] "/Return/ReturnHeader"
# [3] "/Return/ReturnHeader/ReturnTs"
答案 1 :(得分:0)
这是使用&#34; xml2&#34;的解决方案。包。我写了这个函数来找到每个节点的阀门,但在你的情况下,我们只是想找出属性&#34; id&#34;对于每个节点。
目的是找到没有子节点的所有顶级节点并提取它们的值,然后移动到带子节点的节点。然后递归地重复此函数,直到找到并处理了最大的后代节点。
library(xml2)
file<-read_xml('<node id="A">
<node id = "AA">
<node id = "AAA"></node>
</node>
<node id = "AB">
</node>
<node id = "AC">
</node>
</node>')
findchildren<-function(nodes, df){
numchild<-sapply(nodes, function(x){length(xml_children(x))})
#extract out the attribute, value and parents
xmlattr<-xml_attr(nodes[numchild==0], "id")
#xmlvalue<-xml_text(nodes[numchild==0]) #value of node
xmlpath<-sapply(nodes[numchild==0], function(x) {toString(rev(xml_attr(xml_parents(x), "id")))})
#dftemp<-data.frame(xmlattr, xmlvalue, xmlpath)
dftemp<-data.frame(xmlpath, xmlattr)
#merge results back to master df
df<-rbind(df, dftemp)
print(dim(df)) #Print statement for status
#End of recursion
if (sum(numchild)>0){
findchildren(xml_children(nodes[numchild>0]), df) }
else{ return(df)}
}
df<-data.frame()
df<-findchildren(xml_children(file), df)
apply(df, 1, toString)
此功能输出2列数据帧。第一列是第二列中节点的xml路径。我使用apply
命令将这两列合并为最终解决方案。最终列表的顺序不是基于文档的原始构造,而是列出父母,然后是孩子,孙子节点....
此函数重复调用rbind
不是最有效的方法,但如果子级别的数量不是太大,则可以接受。
希望这适合你。