读取R中的XML文件,并在节点具有不同长度和内容时创建数据帧

读取R中的XML文件,并在节点具有不同长度和内容时创建数据帧,r,xml,dataframe,parsing,xml-parsing,R,Xml,Dataframe,Parsing,Xml Parsing,我正在尝试从XML文件创建dataframe对象。这项任务似乎很简单,但经过多次尝试,我无法准确地提取出我想要的东西 原始数据来自这里: 基本上,文档有超过17K个同名节点,即“FICHES”。其中一个“子节点”是“集团能力”。“子节点”有另一个称为“BLOC_competencies”(区别是BLOC中的S),这个节点有两个我感兴趣的节点:CODE和LIBELLE 但是,并非所有“FICHES”都具有相同的属性和/或子节点。此外,其中一些有1个“集团能力”,有1个、2个、3个或根本没有要素

我正在尝试从XML文件创建dataframe对象。这项任务似乎很简单,但经过多次尝试,我无法准确地提取出我想要的东西

原始数据来自这里:

基本上,文档有超过17K个同名节点,即“FICHES”。其中一个“子节点”是“集团能力”。“子节点”有另一个称为“BLOC_competencies”(区别是BLOC中的S),这个节点有两个我感兴趣的节点:CODE和LIBELLE

但是,并非所有“FICHES”都具有相同的属性和/或子节点。此外,其中一些有1个“集团能力”,有1个、2个、3个或根本没有要素

以下(以及其他帖子)我尝试提取根节点并使用xpath访问元素:

# Import the file after zip extraction
RNCP_aout2020 <- xmlParse("U:/RNCP_2020/Fiches-rncp-2020-08-03/export_fiches_RNCP_2020-08-03.xml", encoding = "UTF-8")

# Finding root node
rootNode <- xmlRoot(RNCP_aout2020)

BLOCS_COMPETENCES <- as.data.frame(xpathSApply(rootNode, '/FICHES/FICHE/BLOCS_COMPETENCES/BLOC_COMPETENCES/CODE', xmlValue))
#解压缩后导入文件
RNCP_aout2020可变数量的“集团能力”确实使问题复杂化。在下面的脚本中,解析出所有fiche节点,然后循环遍历每个节点以检索所需的代码和库。还需要检查零长度代码和诽谤。由于fiche的列表很长,lapply语句需要一段时间才能完成

library(xml2)
library(dplyr)

#read the document
page <- read_xml("export_fiches_RNCP_2020-08-03.xml")

#read all fiches nodes
fiches <- xml_find_all(page, "//FICHE")

#parse each fiches
dfs <-lapply(fiches, function(node){
   id <- node %>% xml_find_first(".//ID_FICHE")  %>% xml_text()
   codes <-  node %>% xml_find_all(".//BLOC_COMPETENCES/CODE") %>% xml_text()
   libelles <- node %>% xml_find_all(".//BLOC_COMPETENCES/LIBELLE")%>% xml_text()
   #correct for codes which don't exist
   if (length(codes) <1 ) {codes = NA}
   if (length(libelles) <1 ) {libelles = NA}

   df<- data.frame(id, codes, libelles, stringsAsFactors = FALSE)
})

#merge all of the data frames
answer <- bind_rows(dfs)
库(xml2)
图书馆(dplyr)
#阅读文件
页面%xml\u text()
#对于不存在的代码正确
if(length(codes)考虑转换原始XML以提取所需的节点。然后,使用便利处理程序
xmlToDataFrame
,避免
for
apply
家族循环或
if
逻辑

作为一种独立的、可移植的行业语言,有许多方法可以运行XSLT1.0,包括通过其他语言(Java、Python、PHP)或使用R包
XSLT

XSLT(另存为.xsl文件,下面使用的一个特殊的.xml文件)

方法2(在名为style.xsl的文件中使用上述XSLT)

R+
xslt

library(XML)

setwd("...")
system("xsltproc -o transformed.xml style.xsl export_fiches_RNCP_2020-08-03.xml")

doc <- xmlParse("transformed.xml")
doc
# <FICHES>
#   <BLOC_COMPETENCES>
#     <ID_FICHE>3614</ID_FICHE>
#     <CODE>RNCP13004BC01</CODE>
#     <LIBELLE>Du dérushage au montage</LIBELLE>
#   </BLOC_COMPETENCES>
#   <BLOC_COMPETENCES>
#     <ID_FICHE>3614</ID_FICHE>
#     <CODE>RNCP13004BC02</CODE>
#     <LIBELLE>Analyser un projet cinématographique</LIBELLE>
#   </BLOC_COMPETENCES>
#   <BLOC_COMPETENCES>
#     <ID_FICHE>3614</ID_FICHE>
#     <CODE>RNCP13004BC03</CODE>
#     <LIBELLE>Tourner sur fond d'incrustation </LIBELLE>
#   </BLOC_COMPETENCES>
#   <BLOC_COMPETENCES>
#   ...

df <- xmlToDataFrame(doc)
library(xml2)
library(xslt)
library(XML)

# PARSE XML AND XSLT
doc <- read_xml('export_fiches_RNCP_2020-08-03.xml')
style <- read_xml('style.xsl', package = "xslt")

# TRANSFORM NESTED INPUT INTO FLATTER OUTPUT
new_xml <- as.character(xslt::xml_xslt(doc, style))

# PARSE FLATTER XML
flat_xml <- XML::xmlParse(new_xml, asText=TRUE)

# BUILD DATA FRAME
df <- xmlToDataFrame(doc)
库(xml2)
库(xslt)
库(XML)
#解析XML和XSLT

博士,非常感谢你的完整回答!但是,我必须承认,我对你在回答的第一部分中所说的内容并不太熟悉。有没有初学者指南(或者更好的是认证在线课程)您可能会推荐?我也很好奇您是如何获得JSS格式的示例或预览的。我尝试了您编写的代码,但遇到以下错误:在(函数(类,fdef,mtable)中出错:找不到用于签名的函数“xmlToDataFrame”“xml_document”“missing”“missing”“missing”“missing”的继承方法我忘了添加重要的说明:(另存为.xsl文件,一个特殊的.xml文件)。请参阅编辑。无需特殊课程。您可能听说过SQL,它是一种外部专用声明性语言,R可以运行它从关系数据库检索数据。XSLT也是一种外部专用声明性语言,R可以运行它进行转换(如展平)XML文件,使用特殊的XML文件来运行其代码。我在R中展示了两种方法:使用Unix机器(Mac/Linux)上可用的外部处理器还有一个包。注意:不需要循环,也不需要一个小时!我再次尝试了您的替代方案,因为另一个解决方案需要大量的时间,但我并没有真正让它发挥作用。无论如何,谢谢您。我希望它能帮助其他人。您无法安装
xslt
包(与
xml2
的姐妹)?错误是什么?你的帖子表明你有
XML
,并且接受了你的答案
xml2
。我让xslt包正常工作。我认为这与更新问题有关。无论如何,我确实听说过SQL,我知道什么是关系数据库,我知道我不需要循环来访问信息。我没有得到的是第一个你答案的一部分(以“非常感谢你的回答”开头的那部分!如果你不介意的话,我可以问一下这在你的机器上花了多少时间吗?我甚至尝试了并行代码(McLappy),但任务就是没有执行(等待了超过30mn).这里有一些新闻。留一个小时左右,完成任务。效果很好!我将此标记为最终答案,因为它比另一个更适合我使用R的经验。我担心你会问这个问题。我的3.2 GHz Core i5大约需要20分钟。我不认为循环中的每个迭代都需要那么长的时间t只是大量迭代的一个例子,因此并行运行它可能不是一个真正的节省时间的方法。
library(XML)

setwd("...")
system("xsltproc -o transformed.xml style.xsl export_fiches_RNCP_2020-08-03.xml")

doc <- xmlParse("transformed.xml")
doc
# <FICHES>
#   <BLOC_COMPETENCES>
#     <ID_FICHE>3614</ID_FICHE>
#     <CODE>RNCP13004BC01</CODE>
#     <LIBELLE>Du dérushage au montage</LIBELLE>
#   </BLOC_COMPETENCES>
#   <BLOC_COMPETENCES>
#     <ID_FICHE>3614</ID_FICHE>
#     <CODE>RNCP13004BC02</CODE>
#     <LIBELLE>Analyser un projet cinématographique</LIBELLE>
#   </BLOC_COMPETENCES>
#   <BLOC_COMPETENCES>
#     <ID_FICHE>3614</ID_FICHE>
#     <CODE>RNCP13004BC03</CODE>
#     <LIBELLE>Tourner sur fond d'incrustation </LIBELLE>
#   </BLOC_COMPETENCES>
#   <BLOC_COMPETENCES>
#   ...

df <- xmlToDataFrame(doc)
library(xml2)
library(xslt)
library(XML)

# PARSE XML AND XSLT
doc <- read_xml('export_fiches_RNCP_2020-08-03.xml')
style <- read_xml('style.xsl', package = "xslt")

# TRANSFORM NESTED INPUT INTO FLATTER OUTPUT
new_xml <- as.character(xslt::xml_xslt(doc, style))

# PARSE FLATTER XML
flat_xml <- XML::xmlParse(new_xml, asText=TRUE)

# BUILD DATA FRAME
df <- xmlToDataFrame(doc)