Поскольку вы используете xml2
и вам требуются различные узлы данных, которые различаются по вложенным уровням, рассмотрим XSLT , язык специального назначения (например, SQL), предназначенный для преобразования файлов XML. В R пакет xslt
, родственный модулю xml2
, может запускать сценарии XSLT 1.0. Рекурсивная шаблонная природа XSLT помогает избежать сложных вложенных циклов или отображений на уровне приложений, в данном случае R. Плюс XSLT является переносимым (например, SQL) и может быть запущен вне R.
Хотя это может быть целоеНовая концепция, выходящая из левого поля, требующая обучения, позволяет сглаживать ваш XML в соответствии с двумерной структурой, необходимой для наборов данных. Вы также отделяете обработку XML (XSLT) от обработки данных (R). В частности, поддерживается только уровень Player с соответствующими данными Team , перенесенными вниз (см. Демонстрацию).
XSLT (сохранить как. xsl, специальный XML-файл)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/SoccerFeed|SoccerDocument">
<xsl:apply-templates select="*"/>
</xsl:template>
<xsl:template match="Team">
<xsl:apply-templates select="Player"/>
</xsl:template>
<xsl:template match="Team/@*">
<xsl:element name="{concat('team_', name(.))}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
<xsl:template match="Player">
<xsl:copy>
<xsl:apply-templates select="ancestor::Team/@*"/>
<xsl:copy-of select="Name|Position"/>
<xsl:apply-templates select="@*|Stat"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Player/@*">
<xsl:element name="{name(.)}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
<xsl:template match="Stat">
<xsl:element name="{@Type}">
<xsl:value-of select="text()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Онлайн-демонстрация
R (приводит к кадру данныхвсе типы символов)
library(xml2)
library(xslt)
library(dplyr)
# INPUT SOURCE
doc <- read_xml("/path/to/Input.xml")
style <- read_xml("/path/to/Style.xsl", package = "xslt")
# TRANSFORM
new_xml <- xml_xslt(doc, style)
# RETRIEVE Player NODES
recs <- xml_find_all(new_xml, "//Player")
# BIND EACH CHILD TEXT AND NAME TO Player DFs
df_list <- lapply(recs, function(r)
data.frame(rbind(setNames(xml_text(xml_children(r)),
xml_name(xml_children(r)))),
stringsAsFactors = FALSE)
)
# BIND ALL DFs TO SINGLE MASTER DF
final_df <- bind_rows(df_list)