背景:
我有一个具有以下结构的XML文档:
<records>
<record id="512" size="1">
<user id="8412" origin="ab"/>
<category id="105">Certificates</category>
<rating>80</rating>
<text>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</text>
</record>
<record id="452" size="2">
<user id="7623" origin="bb"/>
<category id="105">Certificates</category>
<rating>70</rating>
<text>
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</text>
</record>
</records>
我要做什么:
使用R,我试图将XML信息转换为数据框,其中每一行代表一个记录,每一列代表该记录的属性或文本数据(目的是包括存在的所有数据)在XML文档中。)
这是最终输出应如下所示:
Record ID | Size | User ID | ... | Text |
452| 2| 7623| ... | Lorem ipsum... |
此外,由于大约有1,000,000条记录,并且包含这些记录的文件约为500MB,因此我试图找到一种相对有效的方法。
到目前为止,我已经尝试过:
我已经查看了与该主题相关的许多问题,但是没有一个提供了适用于这种情况的解决方案。
首先,我尝试使用以下代码在XML包中使用'xmlToDataFrame'函数,但它仅提取文本数据,而不提取属性:
library(XML)
doc = xmlParse("My_document.xml")
xmldf = xmlToDataFrame(doc, nodes = "//record")
xmldf = xmlToDataFrame(nodes = getNodeSet(doc, "//record"))
尽管我尝试在最初导入XML文档的过程中确实提取了相关的属性数据,但是当我尝试使用flatxml包时,也会发生同样的情况:
library(flatxml)
doc = fxml_importXMLFlat("My_document.xml")
xmldf = fxml_toDataFrame(xml_original, siblings.of = 2)
我还尝试了使用xml2包的稍微不同的方法:
library(xml2)
doc <- read_xml('My_document.xml')
rows <- xml_children(doc)
data.frame(
Record_ID = as.numeric(xml_attr(rows,"id")),
Size = as.numeric(xml_attr(rows,"size")),
User_ID = as.numeric(xml_attr(rows,"id")),
Origin = as.character(xml_attr(rows,"origin")),
Category = as.character(xml_text(rows,"category")),
Category_ID = as.numeric(xml_attr(rows,"id")),
Rating = as.numeric(xml_text(rows,"rating")),
Text = as.character(xml_text(rows,"text"))
) -> xmldf
在这里,我遇到了一系列不同的问题:我能够提取属性数据,但只能从“记录”节点中提取。这意味着它将复制“ User_ID”记录中的“ id”数据,并且无法访问诸如“ origin”属性之类的相关数据。此外,每次我尝试提取文本信息时,此过程还将同时从所有节点提取所有文本信息。
答案 0 :(得分:1)
假设每个记录 user 和同级标记,请考虑使用内部方法xmlAttrsToDataFrame
和元素xmlToDataFrame
绑定属性。 >。
library(XML)
...
# BIND ATTRIBUTES AND ELEMENTS
record_df <- cbind(XML:::xmlAttrsToDataFrame(getNodeSet(doc, path='//record')),
XML:::xmlAttrsToDataFrame(getNodeSet(doc, path='//user')),
xmlToDataFrame(doc, nodes = getNodeSet(doc, "//record"))
)
# RENAME COLUMNS
record_df <- setNames(record_df, c("record_id", "record_size", "user_id", "user_origin",
"record_user", "record_category", "record_rating", "record_text"))
record_df
# record_id record_size user_id user_origin record_user record_category record_rating record_text
# 1 512 1 8412 ab Certificates 80 \nLorem ipsum dolor ...
# 2 452 2 7623 bb Certificates 70 \nUt enim ad minim ...