Prof. Walmes Marques Zeviani
18 Abr 2017
handlers =
das funções {xml,html}Parse()
.Figura 1: Nome das funções handlers para uso no DOM. Fonte: NOLAN; LANG (2013).
library(XML)
h <- xmlParse("./earth-quake.xml")
summary(h)
## $nameCounts
##
## param event merge
## 27 4 1
##
## $numNodes
## [1] 32
h
## <?xml version="1.0"?>
## <!-- O mesmo evento foi copiado para criar um arquivo minimamente
## interessante -->
## <merge>
## <event id="1" network-code="NC" time-stamp="2012/11/12_16:25:49 " version="0">
## <param name="latitude" value="38.7953"/>
## <param name="longitude" value="-122.7520"/>
## <param name="depth" value="1.7"/>
## <param name="magnitude" value="0.9"/>
## <param name="magnitude-type-ext" value="Mcd = coda duration magnitude"/>
## <param name="num-stations-mag" value="4"/>
## <param name="stand-mag-error" value="0.0"/>
## </event>
## <event id="2" network-code="NC" time-stamp="2012/11/12_16:25:49 " version="0">
## <param name="latitude" value="38.7953"/>
## <param name="longitude" value="-122.7520"/>
## <param name="depth" value="1.7"/>
## <param name="magnitude" value="0.9"/>
## <param name="magnitude-type-ext" value="Mcd = coda duration magnitude"/>
## <param name="num-stations-mag" value="4"/>
## <param name="stand-mag-error" value="0.0"/>
## </event>
## <event id="3" network-code="NC" time-stamp="2012/11/12_16:25:49 " version="0">
## <param name="latitude" value="38.7953"/>
## <param name="longitude" value="-122.7520"/>
## <param name="depth" value="1.7"/>
## <param name="magnitude" value="0.9"/>
## <param name="magnitude-type-ext" value="Mcd = coda duration magnitude"/>
## <param name="num-stations-mag" value="4"/>
## <param name="stand-mag-error" value="0.0"/>
## </event>
## <event id="4" network-code="NC" time-stamp="2012/11/12_16:25:49 " version="0">
## <param name="latitude" value="38.7953"/>
## <param name="longitude" value="-122.7520"/>
## <param name="depth" value="1.7"/>
## <param name="magnitude-type-ext" value="Mcd = coda duration magnitude"/>
## <param name="num-stations-mag" value="4"/>
## <param name="stand-mag-error" value="0.0"/>
## </event>
## </merge>
##
# Atributos dos quais serão extraídos os valores em cada <param>.
varNames <- c("latitude", "longitude", "depth", "magnitude")
# Função que será executada sobre os elementos <param>.
paramFun <- function(node) {
var <- xmlGetAttr(node, "name")
if (var %in% varNames)
values[[var]] <<- c(values[[var]], xmlGetAttr(node, "value"))
}
# Objeto vazio que será preenchido pela chamada da função paramFun().
values <- structure(replicate(length(varNames),
character(),
simplify = FALSE),
names = varNames)
# Faz o parse usando handlers.
xmlParse("./earth-quake.xml",
handlers = list(param = paramFun))
## $param
## function (node)
## {
## var <- xmlGetAttr(node, "name")
## if (var %in% varNames)
## values[[var]] <<- c(values[[var]], xmlGetAttr(node, "value"))
## }
## <bytecode: 0x6363b28>
# Tamanho dos vetores.
sapply(values, length)
## latitude longitude depth magnitude
## 4 4 4 3
# Função que vai ser executada quando passar por elementos <merge>.
mergeFun <- function(node) {
num <- xmlSize(node)
# Pré-aloca objeto conforme número de eventos.
values <<- structure(replicate(length(varNames),
rep(NA, num),
simplify = FALSE),
names = varNames)
counter <<- 0
}
# Função que vai ser executada quando passar por elementos <event>.
eventFun <- function(node) {
counter <<- counter + 1L
}
# Função que será executada quando passar por elementos <param>.
paramFun <- function(node) {
var <- xmlGetAttr(node, "name")
if (var %in% varNames)
values[[var]][counter] <<- xmlGetAttr(node, "value")
}
# parentFirst = {TRUE, FALSE}: Dos nós externos para os internos?
xmlParse("./earth-quake.xml",
parentFirst = TRUE,
handlers = list(param = paramFun,
merge = mergeFun,
event = eventFun))
## $param
## function (node)
## {
## var <- xmlGetAttr(node, "name")
## if (var %in% varNames)
## values[[var]][counter] <<- xmlGetAttr(node, "value")
## }
## <bytecode: 0x3f9fce8>
##
## $merge
## function (node)
## {
## num <- xmlSize(node)
## values <<- structure(replicate(length(varNames), rep(NA,
## num), simplify = FALSE), names = varNames)
## counter <<- 0
## }
##
## $event
## function (node)
## {
## counter <<- counter + 1L
## }
## <bytecode: 0x38f2320>
# Resultado.
as.data.frame(values)
## latitude longitude depth magnitude
## 1 38.7953 -122.7520 1.7 0.9
## 2 38.7953 -122.7520 1.7 0.9
## 3 38.7953 -122.7520 1.7 0.9
## 4 38.7953 -122.7520 1.7 <NA>
closures
.GlobalEnv
.# Uma única função que define as funções handlers e cria os objetos que
# serão compartilhados entre todas elas. Todos, funções e objetos, são
# definidos dentro do escopo da função quakeHandlers().
quakeHandlers <- function() {
# Cria as variáveis que serão preenchidas/incrementadas.
counter <- 0
values <- NULL
# Função para elementos <param>.
paramFun <- function(node) {
var <- xmlGetAttr(node, "name")
if (var %in% varNames)
values[[var]][counter] <<- xmlGetAttr(node, "value")
}
# Função para elementos <event>.
eventFun <- function(node) {
counter <<- counter + 1L
}
# Função para elementos <merge>.
mergeFun <- function(node) {
num <- xmlSize(node)
values <<- structure(replicate(length(varNames),
rep(NA, num),
simplify = FALSE),
names = varNames)
counter <<- 0
}
# Retorno da função é um conjunto de funções.
list(event = eventFun,
merge = mergeFun,
param = paramFun,
.result = function() {
data.frame(lapply(values, as.numeric))
})
}
hand <- quakeHandlers()
xmlParse("./earth-quake.xml",
parentFirst = TRUE,
handlers = hand)
## $event
## function (node)
## {
## counter <<- counter + 1L
## }
## <bytecode: 0x5677f78>
## <environment: 0x52b9a78>
##
## $merge
## function (node)
## {
## num <- xmlSize(node)
## values <<- structure(replicate(length(varNames), rep(NA,
## num), simplify = FALSE), names = varNames)
## counter <<- 0
## }
## <bytecode: 0x62f64c0>
## <environment: 0x52b9a78>
##
## $param
## function (node)
## {
## var <- xmlGetAttr(node, "name")
## if (var %in% varNames)
## values[[var]][counter] <<- xmlGetAttr(node, "value")
## }
## <bytecode: 0x55b77c8>
## <environment: 0x52b9a78>
##
## $.result
## function ()
## {
## data.frame(lapply(values, as.numeric))
## }
## <bytecode: 0x50b6370>
## <environment: 0x52b9a78>
hand$.result()
## latitude longitude depth magnitude
## 1 38.7953 -122.752 1.7 0.9
## 2 38.7953 -122.752 1.7 0.9
## 3 38.7953 -122.752 1.7 0.9
## 4 38.7953 -122.752 1.7 NA
handlers =
da função xmlEventParse()
.Figura 2: Nome das funções handlers para uso no SAX. Fonte: NOLAN; LANG (2013).
system("cat ./exchange-rates.xml")
saxHandlers <- function(currencies = c("USD", "NZD")) {
# Cria os objetivos a serem preenchidos/incrementados.
rates <- vector("list", length(currencies))
names(rates) <- currencies
times <- numeric()
day <- 0
# Função que vai operar quando encontrar tags de abertura.
startElement <- function(name, attrs) {
# Se o nome do elemento for diferente de "Cube" -> saia.
if (name != "Cube") {
return(NULL)
}
# Se "time" for um dos atributos.
if ("time" %in% names(attrs)) {
# Incremente o contador.
day <<- day + 1
# Passe o valor para o vetor.
times[day] <<- attrs["time"]
return(TRUE)
}
# Se "currency" for um dos atributos e tiver o valor que
# queremos.
if ("currency" %in% names(attrs) &&
attrs["currency"] %in% currencies) {
# Extraia os valores e lance nos vetores.
rates[[attrs["currency"]]][day] <<- attrs["rate"]
}
return(TRUE)
}
# Retorno da função é uma lista com funções.
list(startElement = startElement,
rateData = function() {
list(times = times,
rates = rates)
})
}
sh <- saxHandlers()
xmlEventParse("./exchange-rates.xml", handlers = sh)
## $startElement
## function (name, attrs)
## {
## if (name != "Cube") {
## return(NULL)
## }
## if ("time" %in% names(attrs)) {
## day <<- day + 1
## times[day] <<- attrs["time"]
## return(TRUE)
## }
## if ("currency" %in% names(attrs) && attrs["currency"] %in%
## currencies) {
## rates[[attrs["currency"]]][day] <<- attrs["rate"]
## }
## return(TRUE)
## }
## <bytecode: 0x540da50>
## <environment: 0x402c190>
##
## $rateData
## function ()
## {
## list(times = times, rates = rates)
## }
## <bytecode: 0x54bb270>
## <environment: 0x402c190>
exchange.rate <- sh$rateData()
exchange.rate
## $times
## [1] "2006-10-06" "2006-10-05" "2006-10-04" "2006-10-03" "2006-10-02"
##
## $rates
## $rates$USD
## [1] "1.2664" "1.2700" "1.2626" "1.2536" "1.2901"
##
## $rates$NZD
## [1] NA NA "1.2941" NA "1.3030"
NOLAN, D.; LANG, D. XML and Web Technologies for Data Sciences with R. Springer New York, 2013.