r - 将 XML 文本读入 tibble
问题描述
我想像这样获取一个 xml 文件(我称之为“2019-05-24.xml”):
<file>
<header>
<filename>2019-05-24</filename>
</header>
<body>
<div type="article">
<head>First test article</head>
<p>Some information.</p>
<p>Some other information.</p>
</div>
<div type="section" feature="essay">
<head>Test essay</head>
<p>An argument.</p>
<p>Supporting evidence.</p>
</div>
</body>
</file>
把它变成这样的小标题
# A tibble: 3 x 6
filename seq type feature head text
<chr> <int> <chr> <chr> <chr> <chr>
1 2019-05-24.xml 1 article NA First test "Some information. Other information. Yet…
2 2019-05-24.xml 2 section essay Test essay "An argument. Supporting evidence."
3 2019-05-24.xml 3 index NA NA "Article.....1 Essay....2"
这让我走到了一半:
sample <- "2019-05-24.xml"
extract_data <- function(x){
divs <- x %>%
read_xml() %>%
xml_child(2) %>%
xml_find_all(".//div")
text <- xml_text(divs)
type <- xml_attr(divs, "type")
feature <- xml_attr(divs, "feature")
seq <- seq_along(divs)
test_tibble <- tibble(filename = x, seq = seq, type = type, feature = feature, text = text)
}
lapply(sample, extract_data)
不幸的是,结果连接了head
和p
文本:
# A tibble: 3 x 5
filename seq type feature text
<chr> <int> <chr> <chr> <chr>
1 2019-05-24.… 1 article NA "First test articleSome information.\n Other in…
2 2019-05-24.… 2 section essay Test essayAn argument.Supporting evidence.
3 2019-05-24.… 3 index NA Article.....1Essay....2
问题一:头部
如果我head
以与提取文本相同的方式提取
head <- sample %>%
read_xml() %>%
xml_child(2) %>%
xml_find_all(".//div/head//text()")
我收到一个错误,因为第三个div
不包含head
:
Error: Tibble columns must have consistent lengths, only values of length one are recycled:
* Length 2: Column `head`
* Length 3: Columns `seq`, `type`, `feature`
如果aNA
中没有,我可以让这个函数返回吗?head
div
问题 2:在 div 中读取文本
我只想阅读divs
列表中三个项目或节点中的每一个中的文本。我可以使类似text <- divs %>% xml_children %>% xml_text()
(返回整个文件中的每个孩子)在每个节点上单独工作吗?我尝试了各种apply()
变体。xml_find_all
我认为我在 XPath 和and上做错了xml_text
,但我想不通。
解决方案
为了解决您的问题,需要单独解析每个 div,然后创建一个数据框列表,然后将所有内容 cbind 在一起。
library(xml2)
library(tibble)
sample <- "2019-05-24.xml"
extract_data <- function(x){
#read file
file<-read_xml(x)
#extract divs, get type attribute and
divs <- file %>% xml_find_all(".//div")
type <- xml_attr(divs, "type")
#find the head and p for each div
#returns a list of data frames
output<-lapply(divs, function(d){
header<- d %>% xml_find_first(".//head") %>% xml_text()
text<-d %>% xml_find_all(".//p") %>% xml_text() %>% paste( collapse = ", ")
data.frame(head=header, text)
})
#bind everything up into a tibble.
answer<-do.call(rbind, output)
test_tibble <- cbind(tibble(filename = x, seq = 1:nrow(answer), type = type), answer)
}
lapply(sample, extract_data)
#[[1]]
filename seq type head text
#1 2019-05-24.xml 1 article First test article Some information., Some other information.
#2 2019-05-24.xml 2 section Test essay An argument., Supporting evidence.
推荐阅读
- javascript - ReactJS 切换汉堡菜单
- python - 循环将数据保存在目录中并在python上打印
- rabbitmq - 在rabbitmq中使用默认交换时,如何允许用户仅发布到特定(而不是全部)队列?
- java - 在一个 jar 中使用 Spring boot 2.x 构建 angular 11
- python - 定位 VideoCapture() 的网络摄像头设备 ID
- sql-server - SQL Server DMV(动态管理视图)未在具有 2 个索引的表上显示上次用户更新信息
- android - 如何将标识符附加到微调器项目?
- c++ - 骑士之旅问题编译没有结束
- input - 它显示系统指标的“无法解析/无效的布尔值”错误
- javascript - 错误 AttributeError:“NoneType”对象没有属性“内核”