解析含内容缺失的XML并生成对应data.frame的问题求助
处理TEI格式XML生成对应data.frame的解决方案
问题背景
需要处理一段存在内容缺失的TEI格式XML,目标是生成每行对应一个<div rend="entry">节点的data.frame,缺失的time或content字段用NA填充。此前尝试两种方法均遇问题:
- 使用
read_xml结合XPath查询时,xml_find_all返回空列表; - 改用
htmlParse相关方法虽能提取字符串,但因部分<div>缺少time或content信息,导致数据与节点的对应关系丢失。
核心问题分析
TEI XML带有命名空间(xmlns="http://www.tei-c.org/ns/1.0"),直接使用XPath查询会因为忽略命名空间而无法匹配节点,这是xml_find_all返回空列表的原因。此外,直接全局提取time和content字符串会打破与<div>节点的一一对应关系,必须针对每个<div>节点单独提取字段。
解决方案代码
# 加载所需包 library(xml2) library(tibble) library(purrr) # 读取TEI XML文件 data_xml <- read_xml("your_xml_file.xml") # 去除命名空间(简化XPath查询) xml_ns_strip(data_xml) # 提取所有rend="entry"的div节点 div_nodes <- xml_find_all(data_xml, "//div[@rend='entry']") # 遍历每个div节点,提取time和content extract_fields <- function(node) { # 提取time:查找当前节点下的head[@rend='time'] time <- xml_find_first(node, "./head[@rend='time']") %>% xml_text(trim = TRUE) time <- ifelse(is.na(time), NA, time) # 提取content:查找当前节点下的p[@rend='content']/hi[@rend='italic'] content <- xml_find_first(node, "./p[@rend='content']/hi[@rend='italic']") %>% xml_text(trim = TRUE) content <- ifelse(is.na(content), NA, content) return(list(time = time, content = content)) } # 应用函数到所有div节点 fields_list <- map(div_nodes, extract_fields) # 转换为data.frame并添加div序号 result_df <- tibble( div = seq_along(div_nodes), time = map_chr(fields_list, ~.x$time), content = map_chr(fields_list, ~.x$content) ) # 查看结果 print(result_df)
代码说明
- 命名空间处理:使用
xml_ns_strip(data_xml)去除TEI的默认命名空间,避免XPath查询时需要指定命名前缀,简化查询逻辑。 - 节点定位:通过
//div[@rend='entry']精准定位所有目标<div>节点,确保只处理需要的条目。 - 逐节点提取:针对每个
<div>节点,分别查询其内部的time和content字段,保证每个字段与节点一一对应;若节点不存在对应字段,自动填充NA。 - 结果整理:将提取的字段列表转换为tibble,并添加div序号,与期望输出格式一致。
输出结果
运行代码后将得到如下格式的data.frame:
| div | time | content |
|---|---|---|
| 1 | TIME_1 | CONTENT1 |
| 2 | TIME_2 | NA |
| 3 | TIME_3 | CONTENT3 |
| 4 | NA | CONTENT4 |
内容的提问来源于stack exchange,提问作者amy
相关产品推荐
相关产品推荐

