Хранение определенных значений узлов XML с помощью R's xmlEventParse - PullRequest
7 голосов
/ 24 сентября 2011

У меня есть большой XML-файл, который мне нужно проанализировать с xmlEventParse в R . К сожалению, онлайн-примеры являются более сложными, чем мне нужно, и я просто хочу пометить соответствующий тег узла, чтобы сохранить соответствующий текст узла (не атрибут), каждый текст в отдельном списке, см. Комментарии в коде ниже:

library(XML)
z <- xmlEventParse(
    "my.xml", 
    handlers = list(
        startDocument   =   function() 
        {
                cat("Starting document\n")
        },  
        startElement    =   function(name,attr) 
        {
                if ( name == "myNodeToMatch1" ){
                    cat("FLAG Matched element 1\n")
                }
                if ( name == "myNodeToMatch2" ){
                    cat("FLAG Matched element 2\n")
                }
        },
        text            =   function(text) {
                if ( # Matched element 1 .... )
                    # Store text in element 1 list
                if ( # Matched element 2 .... )
                    # Store text in element 2 list
        },
        endDocument     =   function() 
        {
                cat("ending document\n")
        }
    ),
    addContext = FALSE,
    useTagName = FALSE,
    ignoreBlanks = TRUE,
    trim = TRUE)
z$ ... # show lists ??

У меня вопрос, как реализовать этот флаг в R (профессионально :)? Плюс: Каков наилучший выбор для оценки N произвольных узлов для сопоставления ... если name = "myNodeToMatchN" ... узлы, избегающие сопоставления регистра?

my.xml может быть просто наивным XML, как

<A>
  <myNodeToMatch1>Text in NodeToMatch1</myNodeToMatch1>
  <B>
    <myNodeToMatch2>Text in NodeToMatch2</myNodeToMatch2>
    ...
  </B>
</A>

Ответы [ 3 ]

8 голосов
/ 25 сентября 2011

Я буду использовать 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 "
2 голосов
/ 11 июля 2014

Для тех, кто может учиться у М.Моргана - вот полный код

fileName = system.file("exampleData", "mtcars.xml", package = "XML")

ourBranches <- function() {
  store <- new.env() 
  record <- function(x, ...) {
    key <- xmlAttrs(x)[["id"]]
    value <- xmlValue(x)
    store[[key]] <- value
  }
  getStore <- function() as.list(store)
  list(record=record, getStore=getStore)
}

branches <- ourBranches()
xmlEventParse(fileName, list(), branches=branches)
head(branches$getStore(), 2)
0 голосов
/ 03 ноября 2016

Метод ветвей не сохраняет порядок событий.Другими словами, порядок 'record' в ветках $ getStore () store отличается от исходного в xml-файле.С другой стороны, методы-обработчики могут сохранять порядок.Вот код:

fileName <- system.file("exampleData", "mtcars.xml", package="XML")
records <- new('list')
variable <- new('character')
tag.open <- new('character')
nvar <- 0
xmlEventParse(fileName, list(startElement = function (name, attrs) {
  tagName <<- name
  tag.open <<- c(name, tag.open)
  if (length(attrs)) {
    attributes(tagName) <<- as.list(attrs)
  }
}, text = function (x) {
  if (nchar(x) > 0) {
    if (tagName == "record") {
      record <- list()
      record[[attributes(tagName)$id]] <- x
      records <<- c(records, record)
    } else {
      if( tagName == 'variable') {
        v <- x
        variable <<- c( variable, v)
        nvar <<- nvar + 1
      }
    }
  }
}, endElement = function (name) {
  if( name == 'record') {
    print(paste(tag.open, collapse='>'))
  }
  tag.open <<- tag.open[-1]
}))

head(records,2)
$``Mazda RX4``
[1] "21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4"

$`Mazda RX4 Wag`
[1] "21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4"

variable
[1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear" "carb"

Еще одним преимуществом использования обработчиков является то, что можно захватывать иерархическую структуру.Другими словами, можно также спасти предков.Одним из ключевых моментов этого процесса является использование глобальных переменных, которым можно присвоить «<< -» вместо «<-». </p>

...