使用 XML2 将 XML 转换为数据帧——SDMX 案例
Convert XML to dataframe using XML2 -- SDMX case
请看一下这个问题中的代表。
SDMX 是一种用于传播统计数据的数据模型,Python 和 R 中有一些工具可以处理它。 SDMX 通常以 XML 文件形式提供(最近也以 JSON 文件形式提供)。
我可以使用专用库处理 reprex 中 url 中给出的简单示例,但我想了解发生了什么,所以我想使用 xml2 重现最终结果......这里是我用头撞墙的地方。
原因是在不久的将来我可能不得不处理复杂的 XML 文件,这些文件接近于 SDMX,但不完全相同,这意味着我需要能够手动完成。
任何建议表示赞赏。
谢谢
library(tidyverse)
library(xml2)
library(rsdmx)
url <- "https://stats.oecd.org/restsdmx/sdmx.ashx/GetData/FDIINDEX/AUT+BEL.4+5+8+9+14.V.INDEX/all?startTime=1997&endTime=2019"
##Very easy if I resort to a dedicated library
sdmx <- readSDMX(url, isURL = T)
stats <- as_tibble(sdmx) ## and I have my nice tibble
print(stats)
#> # A tibble: 130 x 7
#> LOCATION SECTOR RESTYPE SERIES TIME_FORMAT obsTime obsValue
#> <chr> <chr> <chr> <chr> <chr> <chr> <dbl>
#> 1 AUT 4 V INDEX P1Y 1997 0
#> 2 AUT 4 V INDEX P1Y 2003 0
#> 3 AUT 4 V INDEX P1Y 2006 0
#> 4 AUT 4 V INDEX P1Y 2010 0
#> 5 AUT 4 V INDEX P1Y 2011 0
#> 6 AUT 4 V INDEX P1Y 2012 0
#> 7 AUT 4 V INDEX P1Y 2013 0
#> 8 AUT 4 V INDEX P1Y 2014 0
#> 9 AUT 4 V INDEX P1Y 2015 0
#> 10 AUT 4 V INDEX P1Y 2016 0
#> # … with 120 more rows
xmlobj <- read_xml(url)
## and then I do not know how to proceed...
由 reprex package (v0.3.0)
于 2020-09-01 创建
您应该了解 XPath。我在代码中给出注释,帮助大家理解:
library(xml2)
url <- "https://stats.oecd.org/restsdmx/sdmx.ashx/GetData/FDIINDEX/AUT+BEL.4+5+8+9+14.V.INDEX/all?startTime=1997&endTime=2019"
series <- read_xml(url) %>% xml_ns_strip() %>% xml_find_all("//DataSet/Series") # find all Series nodes
# note that the easiest way to read nodes in this file is to remove the namespaces by xml_ns_strip()
data <-
purrr::map_dfr(
series,
function(x) {
data.frame(
LOCATION = x %>% xml_find_first(".//Value[@concept='LOCATION']") %>% xml_attr("value"), # for each Series node, get the first Value node has 'concept' attribute is 'LOCATION' and extract the 'value' attribute value
SECTOR = x %>% xml_find_first(".//Value[@concept='SECTOR']") %>% xml_attr("value"),
RESTYPE = x %>% xml_find_first(".//Value[@concept='RESTYPE']") %>% xml_attr("value"),
SERIES = x %>% xml_find_first(".//Value[@concept='SERIES']") %>% xml_attr("value"),
TIME_FORMAT = x %>% xml_find_first(".//Value[@concept='TIME_FORMAT']") %>% xml_attr("value"),
data.frame(
Time = x %>% xml_find_all(".//Obs/Time") %>% xml_text(trim = TRUE) %>% as.integer(),
ObsValue = x %>% xml_find_all(".//Obs/ObsValue") %>% xml_attr("value") %>% as.numeric()
)
)
}
)
请看一下这个问题中的代表。 SDMX 是一种用于传播统计数据的数据模型,Python 和 R 中有一些工具可以处理它。 SDMX 通常以 XML 文件形式提供(最近也以 JSON 文件形式提供)。 我可以使用专用库处理 reprex 中 url 中给出的简单示例,但我想了解发生了什么,所以我想使用 xml2 重现最终结果......这里是我用头撞墙的地方。
原因是在不久的将来我可能不得不处理复杂的 XML 文件,这些文件接近于 SDMX,但不完全相同,这意味着我需要能够手动完成。 任何建议表示赞赏。 谢谢
library(tidyverse)
library(xml2)
library(rsdmx)
url <- "https://stats.oecd.org/restsdmx/sdmx.ashx/GetData/FDIINDEX/AUT+BEL.4+5+8+9+14.V.INDEX/all?startTime=1997&endTime=2019"
##Very easy if I resort to a dedicated library
sdmx <- readSDMX(url, isURL = T)
stats <- as_tibble(sdmx) ## and I have my nice tibble
print(stats)
#> # A tibble: 130 x 7
#> LOCATION SECTOR RESTYPE SERIES TIME_FORMAT obsTime obsValue
#> <chr> <chr> <chr> <chr> <chr> <chr> <dbl>
#> 1 AUT 4 V INDEX P1Y 1997 0
#> 2 AUT 4 V INDEX P1Y 2003 0
#> 3 AUT 4 V INDEX P1Y 2006 0
#> 4 AUT 4 V INDEX P1Y 2010 0
#> 5 AUT 4 V INDEX P1Y 2011 0
#> 6 AUT 4 V INDEX P1Y 2012 0
#> 7 AUT 4 V INDEX P1Y 2013 0
#> 8 AUT 4 V INDEX P1Y 2014 0
#> 9 AUT 4 V INDEX P1Y 2015 0
#> 10 AUT 4 V INDEX P1Y 2016 0
#> # … with 120 more rows
xmlobj <- read_xml(url)
## and then I do not know how to proceed...
由 reprex package (v0.3.0)
于 2020-09-01 创建您应该了解 XPath。我在代码中给出注释,帮助大家理解:
library(xml2)
url <- "https://stats.oecd.org/restsdmx/sdmx.ashx/GetData/FDIINDEX/AUT+BEL.4+5+8+9+14.V.INDEX/all?startTime=1997&endTime=2019"
series <- read_xml(url) %>% xml_ns_strip() %>% xml_find_all("//DataSet/Series") # find all Series nodes
# note that the easiest way to read nodes in this file is to remove the namespaces by xml_ns_strip()
data <-
purrr::map_dfr(
series,
function(x) {
data.frame(
LOCATION = x %>% xml_find_first(".//Value[@concept='LOCATION']") %>% xml_attr("value"), # for each Series node, get the first Value node has 'concept' attribute is 'LOCATION' and extract the 'value' attribute value
SECTOR = x %>% xml_find_first(".//Value[@concept='SECTOR']") %>% xml_attr("value"),
RESTYPE = x %>% xml_find_first(".//Value[@concept='RESTYPE']") %>% xml_attr("value"),
SERIES = x %>% xml_find_first(".//Value[@concept='SERIES']") %>% xml_attr("value"),
TIME_FORMAT = x %>% xml_find_first(".//Value[@concept='TIME_FORMAT']") %>% xml_attr("value"),
data.frame(
Time = x %>% xml_find_all(".//Obs/Time") %>% xml_text(trim = TRUE) %>% as.integer(),
ObsValue = x %>% xml_find_all(".//Obs/ObsValue") %>% xml_attr("value") %>% as.numeric()
)
)
}
)