1

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

我找到了其他语言的例子:

获取 DOM 树中所有从根到叶路径的列表

但我不确定如何遍历 R 中的节点。我使用的是 xml2 包。

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

4

2 回答 2

2

@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"  
于 2016-07-09T17:47:32.003 回答
0

这是使用“xml2”包的解决方案。我编写了这个函数来查找每个节点的阀门,但在您的情况下,我们只是想确定每个节点的属性“id”。
目的是找到所有没有子节点的顶级节点并提取它们的值,然后移动到有子节点的节点。然后递归地重复这个函数,直到找到并处理了最大的后代节点。

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不是最有效的方法,但如果子节点的数量不是可以接受的太棒了。

希望这对你有用。

于 2016-07-08T02:12:20.473 回答