解析缺少内容的 XML

问题描述 投票:0回答:1

我有一个像这样的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

r xml xpath xml-parsing
1个回答
0
投票

显示的输入格式错误,因此

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
© www.soinside.com 2019 - 2024. All rights reserved.