Я буду использовать fileName
из example(xmlEventParse)
в качестве воспроизводимого примера.У него есть теги record
, которые имеют атрибут id
и текст, который мы хотели бы извлечь.Вместо использования handler
я пойду после аргумента branches
.Это похоже на обработчик, но у него есть доступ ко всему узлу, а не только к элементу.Идея состоит в том, чтобы написать замыкание, в котором есть место для хранения данных, которые мы накапливаем, и функцию для обработки каждой ветви интересующего нас XML-документа. Итак, начнем с определения замыкания - для наших целей - функции, котораявозвращает список функций
ourBranches <- function() {
Нам нужно место для хранения результатов, которые мы накапливаем, выбирая среду так, чтобы время вставки было постоянным (не список, к которому мы должны были бы добавить инеэффективная память)
store <- new.env()
Анализатор событий ожидает, что список функций будет вызван при обнаружении соответствующего тега.Нас интересует тег record
.Функция, которую мы напишем, получит узел документа XML.Мы хотим извлечь элемент id
, который мы будем использовать для хранения (текстовых) значений в узле.Мы добавляем их в наш магазин.
record <- function(x, ...) {
key <- xmlAttrs(x)[["id"]]
value <- xmlValue(x)
store[[key]] <- value
}
Как только документ обработан, нам нужен удобный способ получения наших результатов, поэтому мы добавляем функцию для наших собственных целей, независимо от узлов в документе.
getStore <- function() as.list(store)
, а затем завершить закрытие, возвращая список функций
list(record=record, getStore=getStore)
}
Сложная концепция заключается в том, что среда, в которой определена функция, является частью функции, поэтомукаждый раз, когда мы говорим ourBranches()
, мы получаем список функций и новой среды store
для сохранения наших результатов.Чтобы использовать, вызовите xmlEventParse
для нашего файла с пустым набором обработчиков событий и получите доступ к нашему накопленному хранилищу.
> branches <- ourBranches()
> xmlEventParse(fileName, list(), branches=branches)
list()
> head(branches$getStore(), 2)
$`Hornet Sportabout`
[1] "18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 "
$`Toyota Corolla`
[1] "33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 "