2015-06-29 99 views
2

我有一個具有相同結構的多個xml文件的列表。他們中的一些人有結構錯誤,所以他們無法閱讀,我不能手動控制他們,因爲有太多的文件。我知道我需要暗示try或trycatch函數,我試圖理解它們,但我不瞭解如何在我的案例中精確地使用它們。爲了讓示例容易,我只是想將它們全部轉換爲csv。如何在讀取xml文件時處理錯誤R

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 

來處理我的問題,我要改寫我的代碼五號線(我知道,這是不對的):

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> 

回答

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功能更強大,可以爲您節省大量時間

如果您希望以不同的方式處理特定文本的錯誤和/或警告,您可以grepgrep。在這裏,例如,如果我正在嘗試閱讀的文件不存在,我想要一條消息。我想要那些存在但不能被某些原因讀取的文件路徑。

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

首先,你在你的程序中讀取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) 

結果與lstNA會給你什麼文件失敗的指示。

+0

功能不錯。沒有測試過,但看起來很整齊。 –

+0

這不就是什麼tryCatch確實 – rawr

+0

以一種優雅的方式,因爲你使用一個裝飾器incorporing錯誤代碼處理的。 –