我有几个具有以下结构的XML文档:
read_xml(filename, sep="")) %>% xml_find_all("//_atraso") %>% xml_structure
[[1]]
<_atraso>
<_omsmaximodia [_omsmaximodia]>
<_omsmaximo [_omsmaximo]>
<_omsmedia [_omsmedia]>
...
...
[[32]]
<_atraso>
<_omsmaximo [_omsmaximo]>
<_omsmedia [_omsmedia]>
...
如您所见,_atraso
父标签在某些项目上具有_omsmaximodia
子标记,但在其他项目上没有(在这种情况下,在索引 1 中存在子标记,而在索引 32 处不存在(。
我想读取_omsmaximodia
存在的值,否则读取 0 或 NA。目前我是这样读的:
omsmaximodia <- read_xml(filename, sep="")) %>% xml_find_all("//_omsmaximodia") %>% xml_attr("_omsmaximodia") %>% gsub("\.","",.) %>% gsub(",",".",.) %>% {as.numeric(.)}
但是,当_omsmaximodia
标记不存在时,这不会读取任何内容。运行上面的代码会产生长度为 29 的列表,因为 32 个项目中只有 29 个具有_omsmaximodia
标记。我需要长度为 32,在没有长度的地方读取 0 或 NA。
我可以轻松地将 NA 或 0 添加到列表中,但读取项目的顺序很重要。也就是说,如果项目 30 没有_omsmaximodia
标记,则列表中位置 30 的值必须是 NA 或 0。简单地将 0 或 NA 附加到列表的末尾是不可接受的。
我尝试使用xml_missing
和xml_has_attr
函数找出哪些索引不包含_omsmaximodia
标签,但这些函数似乎并不表示缺少标签,我无法确定它们丢失的索引。
有什么想法吗?
为了保持 xml 文档的结构,您可以尝试将函数分别应用于所有元素。以下示例使用编造的数据进行说明,因为您只绘制了数据结构。
# load packages and read data
library(xml2)
library(purrr)
input <- "<xml>
<_atraso>
<_omsmaximodia></_omsmaximodia>
</_atraso>
<_atraso>
</_atraso>
</xml>"
x <- read_xml(input)
x
#> {xml_document}
#> <xml>
#> [1] <_atraso>n <_omsmaximodia/>n</_atraso>
#> [2] <_atraso>n </_atraso>
我们可以找到感兴趣的标签,但使用传统方法,我们没有得到第二个标签的缺失值:
x %>%
xml_find_all(".//_omsmaximodia")
#> {xml_nodeset (1)}
#> [1] <_omsmaximodia/>
为了解决这个问题,我们用xml_children
更深入一步,然后映射所有元素。第二个元素的结果是一个空节点集。我们可以将map_if
与is_empty
结合使用,将其转换为缺失值。
x %>%
xml_children() %>%
map(xml_find_all, ".//_omsmaximodia") %>%
map_if(is_empty, ~{.x <- NA})
#> [[1]]
#> {xml_nodeset (1)}
#> [1] <_omsmaximodia/>
#>
#> [[2]]
#> [1] NA
根据需要执行的操作,可以使用不同的函数来展平或修改列表结构。
请注意,使用此代码,第二个版本大约慢 4 倍。如果你这样做几次,没关系(第二个查询大约需要 0.75 毫秒,而第一次查询需要 0.2 毫秒(,但如果你经常这样做(即解析许多文档(,这可能会加起来。