Проблемы чтения большого XML-файла с пакетом xml2 и попытки создания рабочего закрытия
Я использую xml2
пакет для чтения огромного XML-файла в память, и команда завершается с ошибкой:
Ошибка: Char 0x0 вне допустимого диапазона [9]
Мой код выглядит следующим образом:
library(xml2)
doc <- read_xml('~/Downloads/FBrf.xml')
Данные можно скачать по адресу ftp://ftp.flybase.net/releases/FB2015_05/reporting-xml/FBrf.xml.gz (около 140 МБ) и распаковать - их объем составляет около 1,8 ГБ.
Кто-нибудь посоветует, как выяснить, какие символы проблематичны или как почистить файл перед его чтением.
РЕДАКТИРОВАТЬ
Хорошо, поскольку файл довольно большой, я искал другие решения по переполнению стека и попытался реализовать решение от Мартина Моргана, которое он представил здесь. Объединить значения в огромные XML-файлы.
Так что я до сих пор сделал следующие строки кода
library(XML)
branchFunction <- function(progress=10) {
res <- new.env(parent=emptyenv()) # for results
it <- 0L # iterator -- nodes visited
list(publication=function(elt) {
## handle 'publication' nodes
if (getNodeSet(elt, "not(/publication/feature/id)"))
## early exit -- no feature id
return(NULL)
it <<- it + 1L
if (it %% progress == 0L)
message(it)
publication <- getNodeSet(elt, "string(/publication/id/text())") # 'key'
res[[publication]] <-
list(miniref=getNodeSet(elt,
"normalize-space(/publication/miniref/text())"),
features= xpathSApply(elt, "//feature/id/text()", xmlValue))
}, getres = function() {
## retrieve the 'res' environment when done
res
}, get=function() {
## retrieve 'res' environment as data.frame
publication <- ls(res)
miniref <- unlist(eapply(res, "[[", "miniref"), use.names=FALSE)
feature <- eapply(res, "[[", "features")
len <- sapply(feature, length)
data.frame(publication=rep(publication, len),
feature=unlist(feature, use.names=FALSE),
miniref=rep(miniref, len))
})
}
branches <- branchFunction()
xmlEventParse("~/Downloads/jnk.xml", handlers=NULL, branches=branches)
# xmlEventParse("~/Downloads/FBrf.xml", handlers=NULL, branches=branches)
branches$get()
Я загружаю XML-файл на свой сервер http://download.dejung.net/jnk.xml
Файл имеет всего несколько килобайт, но проблема в результате. Вторая публикация публикации имеет идентификатор FBrf0162243 и минирезек Schwartz et al., 2003, Mol. Cell. Biol. 23(19): 6876--6886
,
Мои результаты из кода, который я разместил выше, сообщают неверный идентификатор публикации соответствующему мини-файлу. Идентификаторы функций верны....
FBrf0050934 FBgn0003277 Schwartz et al., 2003, Mol. Cell. Biol. 23 (19): 6876--6886
Не уверен, почему мой код сообщает о неправильных значениях, возможно, кто-то может помочь мне с замыканиями, так как это очень ново для меня.
2 ответа
В командной строке я запустил команду iconv -f utf-8 -t utf-8 FBrf.xml > outfile.xml
в вашем файле. Это заметно по глазу, но я не установил R, чтобы проверить это.
(если в Windows вам потребуется установить cygwin, чтобы получить доступ к iconv)
Я иногда сталкиваюсь с сообщениями об ошибках "встроенный NULL", которые могут быть похожи на это (если 0x0
в этом сообщении означает то же самое NULL
выпуск). Мой подход состоит в том, чтобы попытаться удалить их перед чтением в файле, так как я не нашел пакет R, который их игнорирует.
Если вы работаете в Unix или OS X, вы можете вызвать sed
в вашей программе R через:
system( 'sed "s/\\0//g" ~/Downloads/dirty.xml > ~/Downloads/clean.xml' )
Если это не помогает, вы можете расширить этот "черный список" символов - см., Например, Unicode Regex; Неверные символы XML
Если что-то все еще не так, то иногда я делаю белый список символов - удаляю все, что не в указанном наборе символов..
sed 's/[^A-Za-z0-9 _.,"]//g' ~/Downloads/dirty.csv > ~/Downloads/clean.csv
Это тот, который я использую для файлов данных.csv (не волнует </etc.>
), так что вы, возможно, захотите расширить его до чего-то вроде [^[:ascii:]]
:
Если вы работаете в Windows, вам, вероятно, придется выйти за пределы R для этого подхода - например, вы можете использовать Cygwin вместо system()
вызов выше.