作为r

时间:2016-07-07 17:39:40

标签: r xml xml2

我试图将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包。

有没有人解决过这个问题?要求朋友。

2 个答案:

答案 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不是最有效的方法,但如果子级别的数量不是太大,则可以接受。

希望这适合你。