Извлечение вложенных XML-данных с использованием библиотеки R и xml2
У меня есть следующая информация в виде вложенного XML-файла, который я пытаюсь превратить в data.frame для анализа и составления отчетов:
<node TEXT="Cost">
<node TEXT="Scale">
<node TEXT="1 - $0 to $100">
</node>
<node TEXT="2 - $100 to $500">
</node>
<node TEXT="3 - $500 to $1000">
</node>
<node TEXT="4 - $1000 to $5000">
</node>
<node TEXT="6 - $5000 +">
</node>
</node>
<node TEXT="Weight">
<node TEXT="1">
</node>
</node>
</node>
Я могу читать в файле XML и извлечь небольшие порции, как показано ниже:
file <- '<node TEXT="Cost">
<node TEXT="Scale">
<node TEXT="1 - $0 to $100">
</node>
<node TEXT="2 - $100 to $500">
</node>
<node TEXT="3 - $500 to $1000">
</node>
<node TEXT="4 - $1000 to $5000">
</node>
<node TEXT="6 - $5000 +">
</node>
</node>
<node TEXT="Weight">
<node TEXT="1">
</node>
</node>
</node>
'
data <- read_xml(file)
xml_find_all(data,"//node/node[@TEXT = 'Scale']/node/@TEXT")
Но что мне действительно нужно сделать, это получить его в виде data.frame, как показано ниже:
Node1 Node2 Node3
"Cost" "Scale" "1 - $0 to $100"
"Cost" "Scale" "2 - $100 to $500"
"Cost" "Scale" "3 - $500 to $1000"
"Cost" "Scale" "4 - $1000 to $5000"
"Cost" "Scale" "5 - $5000 +"
"Cost" "Weight" "1"
Может ли кто-нибудь указать мне правильное направление?
2 ответа
Вместо того, чтобы использовать xslt
Вы также можете просто перебрать список узлов. Здесь мы выбираем все три узла глубиной, а затем извлекаем атрибут TEXT из всех родителей (и, наконец, связываем его вместе с dplyr
)
library(dplyr)
xml_find_all(doc,"//node/node/node") %>% lapply(function(x) {
list(
NODE1=x %>% xml_parent %>% xml_parent %>% xml_attr("TEXT"),
NODE2=x %>% xml_parent %>% xml_attr("TEXT"),
NODE3=x %>% xml_attr("TEXT")
)
}) %>% bind_rows()
Для того, чтобы изменить XML, я хотел бы использовать xslt
который является языком преобразования XML. В этом случае вы могли бы сделать что-то вроде этого. Здесь я превращаю его в HTML-таблицу, которую я могу легко использовать rvest
разобрать
xslt <- '<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<html><table><xsl:apply-templates select="node/node/node"/></table></html>
</xsl:template>
<xsl:template match="node">
<tr>
<td><xsl:value-of select="../../@TEXT"/></td>
<td><xsl:value-of select="../@TEXT"/></td>
<td><xsl:value-of select="@TEXT"/></td>
</tr>
</xsl:template>
</xsl:stylesheet>'
library(xslt)
library(rvest)
style <- read_xml(xslt)
xml_xslt(data, style) %>% html_table() %>% .[[1]]