我有一个像这样的XML:
<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<teiHeader> ... </teiHeader>
<text>
<body>
<head rend="Body A">DOCUMENT_TITLE</head>
<div rend="entry">
<head rend="time">TIME_1</head>
<p rend="Body A"> INFORMATION A</p>
<p rend="content"> <hi rend="italic"> CONTENT1 </hi> </p>
</div>
<div rend="entry">
<head rend="time">TIME_2</head>
<p rend="Body A"> INFORMATION A</p>
<p rend="Body A"> INFORMATION A</p>
</div>
<div rend="entry">
<head rend="time">TIME_3</head>
<p rend="Body A"> INFORMATION A</p>
<p rend="content">
<hi rend="italic"> CONTENT3 </hi>
</p>
<div rend="entry">
<p rend="Body A"> INFORMATION A</p>
<p rend="content">
<hi rend="italic"> CONTENT4 </hi>
</p>
</div>
</body>
</text>
</TEI>
...有许多缺少的参数,但我想获得一个 data.frame,其中每个“div”都有一行,如下所示:
div | 时间 | 内容 |
---|---|---|
1 | 时间1 | 内容1 |
2 | 时间2 | 不适用 |
3 | 时间3 | 内容3 |
4 | 不适用 | 内容4 |
当参数缺失时,使用 NA。
我尝试这样的方法
data_xml <- read_xml(xmlfile)
div <-xml_find_all(data_xml, xpath = ".//div")
df <- tibble::tibble(
date = div %>% xml_text(),
content = div %>% xml_find_first('./p[@rend="content"/hi[@rend="italic"]]') %>% xml_text()
)
但是
xml_find_all
确实返回一个空列表。
根据一些建议,我尝试这种方式,实际工作
doc <- htmlParse(xmlfile)
div <- getNodeSet(doc, '//div')
dates<- xpathSApply(doc,'//div/text()',xmlValue)
abstracts<-unlist(xpathSApply(doc,'//p[@rend="content"]//hi[@rend="italic"]',xmlValue))
我正确地获得了我想要的字符串,但我失去了对应性,因为许多 div 没有内容或没有时间信息的头部(意味着 div、日期、摘要有不同的长度)。有什么建议么? TIA
显示的输入格式错误,因此
read_xml
会给出错误。由于问题表明它有效,因此在将 XML 移动到问题时一定存在转录错误。我们在最后的注释中的第 4 个之前添加了一个。
由于 XML 使用命名空间,因此首先使用
xml_ns_strip
去除该命名空间以避免出现问题。然后形成适当的 xpath 表达式,生成所需的节点,并将其转换为变量 中的 dcf 格式(这是一种名称:值格式,其中每个字段位于单独的行上,并且空行分隔记录 - 有关详细信息,请参阅
?read.dcf
) dcf
。使用 read.dcf
读取该内容,将生成的字符矩阵转换为数据帧,修复类型并将 div 列转换为序列号。
library(dplyr)
library (xml2)
doc <- read_xml(Lines) # see Note at end for Lines
nodes <- doc %>%
xml_ns_strip() %>%
xml_find_all('//div |
//head[@rend="time"] |
//hi[@rend="italic"]')
dcf <- sapply(nodes, function(x)
if (xml_name(x) == "div") "\ndiv:1"
else paste0(xml_attr(x, "rend"), ":", xml_text(x))
)
dcf
dcf %>%
textConnection() %>%
read.dcf() %>%
as.data.frame() %>%
type.convert(as.is = TRUE) %>%
setNames(c("div", "time", "content")) %>%
mutate(div = cumsum(div))
给予
div time content
1 1 TIME_1 CONTENT1
2 2 TIME_2 <NA>
3 3 TIME_3 CONTENT3
4 4 <NA> CONTENT4