如何在读取xml文件时处理错误R.

时间:2015-06-29 11:55:12

标签: xml r try-catch

我有一个具有相同结构的多个xml文件的列表。其中一些有结构错误,因此无法读取,我无法手动控制它们,因为文件太多。我知道我需要暗示try或trycatch函数,我试图理解它们但我不理解如何在我的情况下使用它们。为了使示例简单,我只想将它们全部转换为csv。

library(XML)
k <- 1
Initial.files<- list.files("/My/Initial/Folder")
for(i in initial.files){
data<-dataTable(xmlToDataFrame(xmlParse(i)))
write.csv(data, file = paste("data",(k)".csv"))
k <- k+1
}

我得到的错误通常如下:

Start tag expected, '<' not found
Error in xmlToDataFrame(xmlParse(i)) :
error in evaluation the argument 'doc' in selecting a method for function 'xmlToDataFrame': Error 1: Start tag expected, '<' not found

要处理我的问题,我必须重写我的第5行代码(我知道这是错的):

data<- if(try(dataTable(xmlToDataFrame(xmlParse(i)))!= "try-error")
else{ haven't looked close to this because i didn't got that far...}...

我希望它能够读取这些文件并给我一个无法读取的文件路径列表。

xml文件的结构如下所示:

<ROWSET>
<ROW>

    <line1>asdf</line1>
    <line2>ghjk</line2> 
</ROW>
</ROWSET>

2 个答案:

答案 0 :(得分:4)

以下是tryCatch的示例。当然,您可以将read.table替换为您的功能,它仍然可以正常工作。

第一个会捕获任何错误,只返回有错误的文件路径(我创建了两个测试文件 - 一个可以被read.table读取而另一个会抱怨)

f <- function(path = "~/desktop/test", ...) {
  lf <- list.files(path = path, ...)
  l <- lapply(lf, function(x) {
    tryCatch(read.table(x, header = TRUE),
             error = function(e) x)
  })
  setNames(l, basename(lf))
}

f(full.names = TRUE)

# $cool_test.txt
#   cool test file
# 1    1    2    3
# 
# $notcool_test.txt
# [1] "/Users/rawr/desktop/test/notcool_test.txt"

tryCatch功能更强大,可以为您节省大量时间

如果您希望以不同方式处理特定文本的错误和/或警告,则可以grep。例如,在这里,如果我试图读取的文件不存在,我想要一条消息。我想要存在的文件路径但由于某种原因无法读取。

f2 <- function(path = "~/desktop/test", ..., lf) {
  lf <- if (!missing(lf)) lf else list.files(path = path, ...)
  l <- lapply(lf, function(x) {
    tryCatch(read.table(x, header = TRUE),
             warning = function(w) if (grepl('No such file', w)) {
               sprintf('%s does not exist', x)
             } else sprintf('Some other warning for %s', x),
             error = function(e) if (grepl('Error in scan', e)) {
               message(sprintf('Check format of %s', x))
               x
              } else message(sprintf('Some other error for %s', x)))
  })
  setNames(l, basename(lf))
}

我添加了一个新参数,因此我可以传递一个文件路径列表,以显示它如何处理不存在的文件:

lf <- c("/Users/rawr/desktop/test/cool_test.txt",
        "/Users/rawr/desktop/test/notcool_test.txt",
        "/Users/rawr/desktop/test/file_does_not_exist.txt")

(out <- f2(lf = lf))

# Check format of /Users/rawr/desktop/test/notcool_test.txt
# $cool_test.txt
#   cool test file
# 1    1    2    3
# 
# $notcool_test.txt
# [1] "/Users/rawr/desktop/test/notcool_test.txt"
# 
# $file_does_not_exist.txt
# [1] "/Users/rawr/desktop/test/file_does_not_exist.txt does not exist"

现在您有一个可以包含数据框,文件路径或其他消息的列表。您可以过滤掉数据框并以多种方式编写它们,这里有两个:

lapply(Filter(is.data.frame, out), function(x) do stuff)

for (ii in out)
  if (is.data.frame(ii)) write.csv(ii) else print('not a data frame')

答案 1 :(得分:1)

首先,您要在程序中加入xml 读取写入 。如果要调试则不好:继续一步一步。

您可以使用robustify功能检查出现问题的时间:

robustify<-function(f,silent=T)
{
    is.error <- function(x) inherits(x, "try-error")
    function(...)
    {
        x =try(f(...),silent=silent)
        if(is.error(x))
            return(NA)
        x
    }
}

robustParsing = robustify(xmlParse)

library(XML)

lst = lapply(list.files("/My/Initial/Folder"), robustParsing )

NAlst的结果会显示哪个文件失败。