使用R和XPATH计算具有相同元素名的所有节点的祖先

wlsrxk51  于 2023-03-10  发布在  其他
关注(0)|答案(1)|浏览(168)

我需要解析一个XML文件,以便它返回具有特定ID的所有节点的内容以及该节点的祖先数。我使用R进行分析,并且我熟悉XML和XML 2包。
我的XML文件看起来像这样:

<wc:COLLECTION xmlns:wc="mywebpage.com">
 <Object NAME="TREE" TYPE="Unknown" STATUS="0">
  <wc:INSTANCE>
   <name>Top_Level</name>
   <partType>Assembly</partType>
   <number>123455</number>
   <wt.part.WTPartUsageLink.uses>
    <wc:INSTANCE>
     <name>Component_1</name>
     <partType>component</partType>
     <number>123456</number>
    </wc:INSTANCE>
   </wt.part.WTPartUsageLink.uses>
   <wt.part.WTPartUsageLink.uses>
    <wc:INSTANCE>
     <name>SUBASSEMBLY</name>
     <partType>separable</partType>
     <number>123457</number>
      <wt.part.WTPartUsageLink.uses>
       <wc:INSTANCE>
        <name>Component_2</name>
        <partType>component</partType>
        <number>123458</number>
       </wc:INSTANCE>
      </wt.part.WTPartUsageLink.uses>
    </wc:INSTANCE>
   </wt.part.WTPartUsageLink.uses>
  </wc:INSTANCE>
 </Object NAME="TREE" TYPE="Unknown" STATUS="0">
<wc:COLLECTION xmlns:wc="mywebpage.com">

最后,我想创建一个如下所示的 Dataframe :
| 人数|姓名|祖先计数|
| - ------|- ------|- ------|
| 小行星123455|顶层|无|
| 小行星123456|组件_1|1个|
| 小行星123457|分组装件|1个|
| 小行星123458|组件_2|第二章|
我使用R中的XML 2包成功地收集了“number”和“name”的所有节点内容,方法如下:

library(XML2)
library(XML)
READ_MY_XML <-read_xml(MY_XML$content)
number <- as.character(xml_text(xml_find_all(READ_MY_XML, xpath = "//number")))
name <- as.character(xml_text(xml_find_all(READ_MY_XML, xpath = "//name")))
df <- tibble(number = number, name = name)

这产生了我需要的3列中的2列。2最后一列是我需要的祖先的计数。
在尝试计算祖先时,我使用了“XPATHSAPPLY”函数。下面是我的示例尝试:

MY_PARSED_XML <- xmlParse(MY_XML)
count_of_ancestors <- xpathSApply(MY_PARSED_XML, "count(//number/ancestor::*)", xmlValue)

这将得出“number”节点的所有祖先的总数。此计数是单数,而不是等于节点总数的一系列数字。
我还尝试通过索引获取单个节点的祖先节点的计数,这样我就可以遍历所有索引位置。

MY_PARSED_XML <- xmlParse(MY_XML)
count_of_ancestors  <- xpathSApply(MY_PARSED_XML, "count(./number[3]/ancestor::*)", xmlValue)

这将导致“0”,这是不正确的。

gjmwrych

gjmwrych1#

在xml2库中有一个xml_parents()函数。用这个函数可以计算结构中父节点的总数。在这种情况下,你需要调整“top_level”的父节点数。

library(xml2)
nodes <- xml_find_all(READ_MY_XML, xpath = ".//name")
number <- as.character(xml_text(xml_find_all(READ_MY_XML, xpath = "//number")))
name <- as.character(xml_text(xml_find_all(READ_MY_XML, xpath = "//name")))

#counts parents and then corrects for the structure
ancestors <- sapply(nodes, function(n) {
   temp <- n %>% xml_parents() %>% length()
   (temp-3)/2
})
df <- tibble(number = number, name = name, ancestors)

> df
# A tibble: 4 × 3
  number name        ancestors
  <chr>  <chr>           <dbl>
1 123455 Top_Level           0
2 123456 Component_1         1
3 123457 SUBASSEMBLY         1
4 123458 Component_2         2

相关问题