将缺少的XML标记读为0或NA?

时间:2018-05-14 15:20:22

标签: r xml

我有几个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不存在。

我可以轻松地将NAs或0添加到列表中,但是读取项目的顺序很重要。也就是说,如果第30项没有_omsmaximodia标签,那么列表中第30位的值必须是NA或0.只需将0或NA附加到列表的末尾是不可接受的。

我尝试使用xml_missingxml_has_attr函数找出哪些索引不包含_omsmaximodia标记,但这些函数似乎并不表示缺少标记,而我无法使用确定他们失踪的指数。

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

为了保留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_ifis_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.75ms,而第一个查询需要0.2ms),但如果你经常这样做(即解析许多文档),这可能会加起来。