grandi risposte di cui sopra! Per i lettori futuri, ogni volta che si affronta un XML complesso che richiede l'importazione R, prendere in considerazione la ristrutturazione del documento XML utilizzando XSLT (un linguaggio di programmazione dichiarativo per scopi speciali che manipola il contenuto XML in varie esigenze di utilizzo finale). Quindi utilizzare semplicemente la funzione xmlToDataFrame()
di R dal pacchetto XML.
Sfortunatamente, R non ha un pacchetto XSLT dedicato disponibile su CRAN-R su tutti i sistemi operativi. Lo SXLT elencato sembra un pacchetto Linux e non può essere utilizzato su Windows. Vedi domande SO senza risposta here e here. Capisco @hrbrmstr (sopra) mantiene un GitHub XSLT project. Tuttavia, quasi tutti i linguaggi generici mantengono i processori XSLT tra cui Java, C#, Python, PHP, Perl e VB.
Di seguito è la rotta Python open-source e poiché il documento XML è piuttosto sfumato, vengono utilizzati due XSLT (ovviamente i guru XSLT possono combinarli in uno solo, ma ho provato perché non avrei potuto farlo funzionare.
FIRST XSLT (utilizzando un recursive template)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- Identity Transform -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="record/text()" name="tokenize">
<xsl:param name="text" select="."/>
<xsl:param name="separator" select="' '"/>
<xsl:choose>
<xsl:when test="not(contains($text, $separator))">
<data>
<xsl:value-of select="normalize-space($text)"/>
</data>
</xsl:when>
<xsl:otherwise>
<data>
<xsl:value-of select="normalize-space(substring-before($text, $separator))"/>
</data>
<xsl:call-template name="tokenize">
<xsl:with-param name="text" select="substring-after($text, $separator)"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="description|variables|categoricalvariable|realvariable">
</xsl:template>
SECONDA XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Identity Transform -->
<xsl:template match="records">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="record">
<record>
<area_name><xsl:value-of select="@label"/></area_name>
<area><xsl:value-of select="data[1]"/></area>
<region><xsl:value-of select="data[2]"/></region>
<palmitic><xsl:value-of select="data[3]"/></palmitic>
<palmitoleic><xsl:value-of select="data[4]"/></palmitoleic>
<stearic><xsl:value-of select="data[5]"/></stearic>
<oleic><xsl:value-of select="data[6]"/></oleic>
<linoleic><xsl:value-of select="data[7]"/></linoleic>
<linolenic><xsl:value-of select="data[8]"/></linolenic>
<arachidic><xsl:value-of select="data[9]"/></arachidic>
<eicosenoic><xsl:value-of select="data[10]"/></eicosenoic>
</record>
</xsl:template>
</xsl:stylesheet>
Python (utilizzando il modulo lxml)
import lxml.etree as ET
cd = os.path.dirname(os.path.abspath(__file__))
# FIRST TRANSFORMATION
dom = ET.parse('http://www.ggobi.org/book/data/olive.xml')
xslt = ET.parse(os.path.join(cd, 'Olive.xsl'))
transform = ET.XSLT(xslt)
newdom = transform(dom)
tree_out = ET.tostring(newdom, encoding='UTF-8', pretty_print=True, xml_declaration=True)
xmlfile = open(os.path.join(cd, 'Olive_py.xml'),'wb')
xmlfile.write(tree_out)
xmlfile.close()
# SECOND TRANSFORMATION
dom = ET.parse(os.path.join(cd, 'Olive_py.xml'))
xslt = ET.parse(os.path.join(cd, 'Olive2.xsl'))
transform = ET.XSLT(xslt)
newdom = transform(dom)
tree_out = ET.tostring(newdom, encoding='UTF-8', pretty_print=True, xml_declaration=True)
xmlfile = open(os.path.join(cd, 'Olive_py.xml'),'wb')
xmlfile.write(tree_out)
xmlfile.close()
R
library(XML)
# LOADING TRANSFORMED XML INTO R DATA FRAME
doc<-xmlParse("Olive_py.xml")
xmldf <- xmlToDataFrame(nodes = getNodeSet(doc, "//record"))
View(xmldf)
uscita
area_name area region palmitic palmitoleic stearic oleic linoleic linolenic arachidic eicosenoic
North-Apulia 1 1 1075 75 226 7823 672 na 60
North-Apulia 1 1 1088 73 224 7709 781 31 61 29
North-Apulia 1 1 911 54 246 8113 549 31 63 29
North-Apulia 1 1 966 57 240 7952 619 50 78 35
North-Apulia 1 1 1051 67 259 7771 672 50 80 46
...
(leggera pulizia sul primo disco è necessario come uno spazio extra è stato aggiunto dopo "na" in XML doc, quindi arachidic
e eicosenoic
sono stati spostati in avanti)
Vorrei usare xml2, se non altro perché Hadley produce costantemente pacchetti di R molto utili e di alta qualità. Probabilmente andrà più liscio e sarà meglio documentato. Differenze in fondo a readme: https://github.com/hadley/xml2 –
abbastanza giusto. xml2, secondo la pagina GitHub, e le mie brevi esperienze, ha un'interfaccia più semplice. R è stato scritto da sviluppatori del core R, ed è pieno di stranezze, mentre Hadley spesso ottiene la semplicità e il bilanciamento del potere giusto, e rende tutto pulito e ordinato. –