如何在R中将XML的device层级节点转换为可区分identifier的DataFrame
解决方案
我们需要分开处理header节点和device节点,同时将每个device下的identifier拆分为可区分的结构,避免合并到单个单元格。以下是具体实现步骤:
1. 加载所需包
先安装并加载用于XML解析和数据整理的工具包:
install.packages(c("xml2", "dplyr", "tidyr")) library(xml2) library(dplyr) library(tidyr)
2. 读取XML并分离header与device节点
# 读取XML文件 doc <- read_xml("D:/xmltest.xml") # 提取header节点(保留原始结构,不转换为DataFrame) header_node <- xml_find_first(doc, ".//header") # 提取所有device节点,后续仅对这些节点做转换 device_nodes <- xml_find_all(doc, ".//device")
3. 转换device节点为DataFrame并处理identifier
GUDID格式中每个device下的identifier包含identifierType和identifierValue两类信息,我们提供两种处理方式:
方式一:将每个identifier展开为单独行(保留device其他字段关联)
# 定义函数处理单个device节点 process_device <- function(node) { # 提取device的基础属性字段 device_base <- xml_attrs(node) %>% as_tibble_row() %>% mutate(across(everything(), as.character)) # 提取当前device下的所有identifier identifiers <- xml_find_all(node, ".//identifier") %>% map_dfr(function(ident) { tibble( identifierType = xml_find_chr(ident, ".//identifierType"), identifierValue = xml_find_chr(ident, ".//identifierValue") ) }) # 合并基础字段与identifier信息(无identifier则仅返回基础字段) if(nrow(identifiers) == 0) { return(device_base) } else { return(bind_cols(device_base, identifiers)) } } # 批量处理所有device节点 device_df <- map_dfr(device_nodes, process_device)
方式二:将不同类型的identifier转为单独列(适合identifier类型固定的场景)
device_df <- map_dfr(device_nodes, function(node) { # 提取device基础字段 base_data <- xml_attrs(node) %>% as_tibble_row() %>% mutate(across(everything(), as.character)) # 提取identifier并转换为宽格式(每种类型对应一列) ident_wide <- xml_find_all(node, ".//identifier") %>% map_dfr(function(ident) { tibble( type = xml_find_chr(ident, ".//identifierType"), value = xml_find_chr(ident, ".//identifierValue") ) }) %>% pivot_wider(names_from = type, values_from = value, names_prefix = "identifier_") # 合并基础字段与宽格式identifier表 bind_cols(base_data, ident_wide) })
4. 保留header节点的信息
如果需要使用header中的内容,可以直接提取具体字段,或保留原始XML结构:
# 提取header的关键字段示例 header_info <- tibble( submissionDate = xml_find_chr(header_node, ".//submissionDate"), source = xml_find_chr(header_node, ".//source") ) # 若需保留原始XML结构,可序列化为字符串保存 header_raw_xml <- xml_serialize(header_node, NULL)
内容的提问来源于stack exchange,提问作者Inho Lee
相关产品推荐
相关产品推荐

