循环遍历酒店XML账单列表提取DettaglioLinee节点数据生成DataFrame
你之前的代码直接对嵌套节点执行unlist操作,会将所有嵌套层级的字段展开为独立列,而不同行的嵌套字段数量、命名存在差异,就会导致列数暴增、大量NA值的问题。
可以使用xml2配合tidyverse系列工具精准提取目标节点,结构化整合数据,实现代码如下:
# 加载所需依赖包 library(xml2) library(dplyr) library(purrr) # 批量读取所有XML文件路径,请将下方路径替换为你存放XML文件的实际文件夹路径 xml_paths <- list.files(path = "./酒店账单XML/", pattern = "\\.xml$", full.names = TRUE) # 定义单份XML文件处理函数 process_single_xml <- function(xml_path) { # 读取XML文件 doc <- read_xml(xml_path) # 用XPath语法精准定位所有DettaglioLinee目标节点 line_nodes <- xml_find_all(doc, "//DatiBeniServizi/DettaglioLinee") # 定义单行节点解析函数 process_line_node <- function(node) { # 提取一级子节点的名称和对应值 child_vals <- xml_children(node) %>% set_names(xml_name(.)) %>% map(xml_text) # 展开嵌套的CodiceArticolo节点为独立列 if ("CodiceArticolo" %in% names(child_vals)) { codice_cols <- xml_children(child_vals$CodiceArticolo) %>% set_names(paste0("CodiceArticolo_", xml_name(.))) %>% map(xml_text) child_vals <- c(child_vals[names(child_vals) != "CodiceArticolo"], codice_cols) } # 处理多个AltriDatiGestionali节点,按数据类型生成对应列 adg_nodes <- xml_find_all(node, "./AltriDatiGestionali") if (length(adg_nodes) > 0) { adg_cols <- map(adg_nodes, ~{ tipo <- xml_text(xml_find_first(., "./TipoDato")) val <- xml_text(xml_find_first(., "./RiferimentoTesto")) set_names(list(val), paste0("AltriDati_", tipo)) }) %>% flatten() child_vals <- c(child_vals[names(child_vals) != "AltriDatiGestionali"], adg_cols) } # 可选:添加源文件名标识,方便后续追溯数据来源 child_vals$source_file <- basename(xml_path) return(as_tibble(child_vals)) } # 合并当前XML内所有行节点数据为单个数据表 return(map_dfr(line_nodes, process_line_node)) } # 批量处理所有XML文件,合并为最终结构化总表 final_df <- map_dfr(xml_paths, process_single_xml)
如果需要将数值类字段转换为数字类型,可以追加如下代码:
final_df <- final_df %>% mutate( across(c(NumeroLinea, Quantita, PrezzoUnitario, PrezzoTotale, AliquotaIVA), as.numeric) )
该方案通过XPath精准定位目标节点,统一处理嵌套结构,不会生成冗余列,也不会出现大量空值,最终输出的final_df就是你需要的结构化汇总表。
内容的提问来源于stack exchange,提问作者Dany
相关产品推荐
相关产品推荐

