2012-10-16 17 views
3

我有一個while循環遍歷一個XML文件,並且對於其中一個節點「url」,其中有時候有無效值。我在此附上了一個try-catch語句來捕獲任何無效值。問題是,無論何時獲取一個無效值,while循環被終止並且程序在該循環之外繼續。如果找到無效值,我需要while循環繼續讀取XML文件的其餘部分。Try-Catch語句結束while循環讀取C#中的XML文件#

這裏是我的代碼:

 XmlTextReader reader = new XmlTextReader(fileName); 
     int tempInt; 

     while (reader.Read()) 
     { 
      switch (reader.Name) 
      { 
       case "url": 
        try 
        { 
         reader.Read(); 
         if (!reader.Value.Equals("\r\n")) 
         { 
          urlList.Add(reader.Value); 
         } 
        } 
        catch 
        {        
         invalidUrls.Add(urlList.Count); 
        } 
        break; 
      } 
     } 

我選擇不包括switch語句的其餘部分,因爲它是不相關的。這裏是我的XML的一個樣本:

<?xml version="1.0" encoding="ISO-8859-1" ?> 
<visited_links_list> 
    <item> 
     <url>http://www.grcc.edu/error.cfm</url> 
     <title>Grand Rapids Community College</title> 
     <hits>20</hits> 
     <modified_date>10/16/2012 12:22:37 PM</modified_date> 
     <expiration_date>11/11/2012 12:22:38 PM</expiration_date> 
     <user_name>testuser</user_name> 
     <subfolder></subfolder> 
     <low_folder>No</low_folder> 
     <file_position>834816</file_position> 
    </item> 
</visited_links_list> 

我能在整個代碼中的例外是類似以下內容:

「」」,十六進制值0×05,是無效字符3887線,位置13.」

+4

什麼是異常,你確定無效輸入是在你的一個案例中嗎?如果它發生在循環頂部的'reader.Read()'調用中,那麼'try' /'catch'塊將無濟於事。另外,如果實際的XML語法無效,那麼無論您做什麼,XmlTextReader都將無法繼續。 –

回答

3

觀察:

你打電話reader.Read()兩次爲每個條目。一旦在while()之內,並且在case之內一次。你真的想跳過記錄嗎?如果源XML中有奇數個條目(因爲reader.Read()將XML流中的指針前進到下一個項目),但這個例外將不會被捕獲,因爲它發生在您的外部try...catch

除此之外:

reader.Read(); /// might return false, but no exception, so keep going... 

if (!reader.Value.Equals("\r\n")) /// BOOM if the previous line returned false, which you ignored 
{ 
    urlList.Add(reader.Value); 
} 
/// reader is now in unpredictable state 

編輯

在寫小說的長度答案的風險...

您收到

錯誤「」,'十六進制值0x05,是一個無效的字符之三。 3887行,位置13。「

表示您的源XML格式錯誤,並且在某個位置以^E(ASCII 0x05)清零,我會看看該行,如果您從供應商處獲得此文件或一項服務,你應該讓他們修復他們的代碼,修正你的XML中的錯誤內容,並糾正你所看到的問題

一旦修復,你的原代碼應該可以工作,使用XmlTextReader因爲這不是最強大的解決方案,並涉及構建一些代碼,Visual Studio將爲您高興地生成:

在VS2012中(我不「T有VS2010安裝任何更多的,但它應該是相同的過程):

  • 的XML樣本您的解決方案

  • 添加在該文件的屬性,設置CustomTool爲「 MSDataSetGenerator「(不含引號)

  • IDE應生成一個.designer.cs文件,其中包含一個可序列化的類,其中包含一個用於XML中每個項目的字段。 (如果沒有,在XML文件中的解決方案資源管理器中單擊鼠標右鍵,選擇「運行自定義工具」。)

enter image description here

  • 使用如下代碼以相同的加載XML模式作爲您的樣品在運行時:

    /// make sure the XML doesn't have errors, such as non-printable characters 
    private static bool IsXmlMalformed(string fileName) 
    { 
        var reader = new XmlTextReader(fileName); 
        var result = false; 
    
        try 
        { 
         while (reader.Read()) ; 
        } 
        catch (Exception e) 
        { 
         result = true; 
        } 
    
        return result; 
    } 
    
    /// Process the XML using deserializer and VS-generated XML proxy classes 
    private static void ParseVisitedLinksListXml(string fileName, List<string> urlList, List<int> invalidUrls) 
    { 
        if (IsXmlMalformed(fileName)) 
         throw new Exception("XML is not well-formed."); 
    
        using (var textReader = new XmlTextReader(fileName)) 
        { 
         var serializer = new XmlSerializer(typeof(visited_links_list)); 
    
         if (!serializer.CanDeserialize(textReader)) 
          throw new Exception("Can't deserialize this XML. Make sure the XML schema is up to date."); 
    
         var list = (visited_links_list)serializer.Deserialize(textReader); 
    
         foreach (var item in list.item) 
         { 
          if (!string.IsNullOrEmpty(item.url) && !item.url.Contains(Environment.NewLine)) 
           urlList.Add(item.url); 
          else 
           invalidUrls.Add(urlList.Count); 
         } 
        } 
    } 
    

您也可以使用xsd.exe工具做到這一點附帶的Windo ws SDK。

+0

當我省略第二個reader.Read()時,它不會讀取節點的內容,reader.Value總是空白。我做了一個斷點,並查看了reader.Name和reader.Value在程序中的不同點,它確實找到了「url」,但reader.Value總是「」。 –

+0

@ user1751367用XML的示例更新您的問題。 –

+0

我按照您的要求包含了一個XML示例。感謝您的幫助順便說一句。 –

-1

使用continue

while (reader.Read()) 
     { 
      switch (reader.Name) 
      { 
       case "url": 
        try 
        { 
         reader.Read(); 
         if (!reader.Value.Equals("\r\n")) 
         { 
          urlList.Add(reader.Value); 
         } 
        } 
        catch 
        { 
         invalidUrls.Add(urlList.Count); 
         continue; 
        } 
        break; 
      } 
     } 
+0

這不應該在他的例子中有所作爲。 'continue'只是跳過當前循環迭代的其餘部分。在這種情況下,所有這些都會跳過「break」和一些花括號。 –

1

我有一種感覺reader留在故障狀態異常被拋出後(如reader.Read();(在switch內,而不是while)最有可能是發生了異常的行reader.Read()while不返回任何東西,它退出。

我做了一個簡單的switch在控制檯應用程序和捕獲和異常在它並且包含循環繼續進行。

var s = "abcdefg"; 
foreach (var character in s) 
{ 
    switch (character) 
    { 
     case 'c': 
      try 
      { 
       throw new Exception("c sucks"); 
      } 
      catch 
      { 
       // Swallow the exception and move on? 
      } 
      break; 
     default: 
      Console.WriteLine(character); 
      break; 
    } 
} 

如果你走過的代碼,它嘗試運行在whilereader.Read()異常被捕獲後?

+0

它在第二個reader.Read()如果發現異常,然後程序脫離while循環時失敗。我現在在原始問題中有一個XML的例子。 –

0

我假設您正在閱讀有效的xml文檔,如myFile.xml。我也假設「url」是你正在尋找的元素。

將文檔加載到XMLDocument類中並使用它來遍歷節點。這應該消除不好的字符,因爲它會將這些字符轉換爲正確的格式,例如&將變成放大器;等..

下面的方法應該提供您提供的示例工作。

 //get the text of the file into a string 
     System.IO.StreamReader sr = new System.IO.StreamReader(@"C:\test.xml"); 
     String xmlText = sr.ReadToEnd(); 
     sr.Close(); 
     //Create a List of strings and call the method 
     List<String> urls = readXMLDoc(xmlText); 
     //check to see if we have a list 
     if (urls != null) 
     { 
      //do somthing 
     } 


    private List<String> readXMLDoc(String fileText) 
    { 
     //create a list of Strings to hold our Urls 
     List<String> urlList = new List<String>(); 
     try 
     { 
      //create a XmlDocument Object 
      XmlDocument xDoc = new XmlDocument(); 
      //load the text of the file into the XmlDocument Object 
      xDoc.LoadXml(fileText); 
      //Create a XmlNode object to hold the root node of the XmlDocument 
      XmlNode rootNode = null; 
      //get the root element in the xml document 
      for (int i = 0; i < xDoc.ChildNodes.Count; i++) 
      { 
       //check to see if it is the root element 
       if (xDoc.ChildNodes[i].Name == "visited_links_list") 
       { 
        //assign the root node 
        rootNode = xDoc.ChildNodes[i]; 
        break; 
       } 
      } 

      //Loop through each of the child nodes of the root node 
      for (int j = 0; j < rootNode.ChildNodes.Count; j++) 
      { 
       //check for the item tag 
       if (rootNode.ChildNodes[j].Name == "item") 
       { 
        //assign the item node 
        XmlNode itemNode = rootNode.ChildNodes[j]; 
        //loop through each if the item tag's elements 
        foreach (XmlNode subNode in itemNode.ChildNodes) 
        { 
         //check for the url tag 
         if (subNode.Name == "url") 
         { 
          //add the url string to the list 
          urlList.Add(subNode.InnerText); 
         } 
        } 
       } 
      } 
     } 
     catch (Exception e) 
     { 
      System.Windows.Forms.MessageBox.Show(e.Message); 
      return null; 
     } 
     //return the list 
     return urlList; 
    } 
+0

此解決方案不適用於我的XML文檔。我用我的XML樣本編輯了我的原始問題。 –

+0

我更新了答案,以顯示如何使用示例讀入和解析出xml文件。如果您仍然有例外情況,最好從提供錯誤的xml文件中發佈文本。 – Sorceri