C# Try Catch语句在循环读取C中的XML文件时结束#

C# Try Catch语句在循环读取C中的XML文件时结束#,c#,while-loop,try-catch,switch-statement,xmltextreader,C#,While Loop,Try Catch,Switch Statement,Xmltextreader,我有一个while循环遍历一个XML文件,对于其中一个节点“url”,其中有时存在无效值。我在这周围放了一个try-catch语句来捕获任何无效值。问题是,每当抓取一个无效值时,while循环被终止,程序继续在该循环之外运行。如果发现无效值,我需要while循环继续读取XML文件的其余部分 这是我的密码: XmlTextReader reader = new XmlTextReader(fileName); int tempInt; while

我有一个while循环遍历一个XML文件,对于其中一个节点“url”,其中有时存在无效值。我在这周围放了一个try-catch语句来捕获任何无效值。问题是,每当抓取一个无效值时,while循环被终止,程序继续在该循环之外运行。如果发现无效值,我需要while循环继续读取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>

http://www.grcc.edu/error.cfm
大急流社区学院
20
2012年10月16日下午12:22:37
2012年11月11日12:22:38下午
测试用户
不
834816
我在整个代码中遇到的异常与以下类似:

““”,十六进制值0x05,是无效字符。第3887行,位置13。”

使用


我有一种感觉,抛出异常后,
reader
处于错误状态(作为
reader.Read();
(在
开关中,而不是
while
)中的
reader.Read()
很可能是发生异常的那一行。然后
while
中的
reader.Read()
不返回任何内容,它退出

我在一个控制台应用程序中做了一个简单的
开关
,在其中捕获和异常,包含的循环继续进行

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;
    }
}
如果您浏览代码,它是否会在捕获异常后在
的同时尝试运行
中的
reader.Read()

您正在为每个条目调用
reader.Read()
两次。在
while()
中调用一次,在
案例中调用一次。您真的想跳过记录吗?如果源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中(我不再安装VS2010,但应该是相同的过程):

  • 将XML示例添加到解决方案中

  • 在该文件的属性中,将CustomTool设置为“MSDataSetGenerator”(不带引号)

  • IDE应该生成一个.designer.cs文件,其中包含一个可序列化的类,该类在XML中的每个项都有一个字段。(如果没有,请在解决方案资源管理器中右键单击XML文件并选择“运行自定义工具”。)

  • 使用如下代码在运行时加载与示例模式相同的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);
            }
        }
    }
    
    ///确保XML没有错误,例如不可打印的字符
    私有静态bool isxmlmorformed(字符串文件名)
    {
    var reader=新的XmlTextReader(文件名);
    var结果=假;
    尝试
    {
    while(reader.Read());
    }
    捕获(例外e)
    {
    结果=真;
    }
    返回结果;
    }
    ///使用反序列化器和VS生成的XML代理类处理XML
    私有静态void ParseVisitedLinksListXml(字符串文件名、列表URL列表、列表无效URL)
    {
    if(isxmlmorformed(文件名))
    抛出新异常(“XML格式不正确”);
    使用(var textleader=newxmltextreader(文件名))
    {
    var serializer=新的XmlSerializer(typeof(已访问链接列表));
    if(!serializer.CanDeserialize(textReader))
    抛出新异常(“无法反序列化此XML。请确保XML架构是最新的。”);
    var list=(已访问链接列表)序列化程序。反序列化(textReader);
    foreach(list.item中的var项)
    {
    如果(!string.IsNullOrEmpty(item.url)和&!item.url.Contains(Environment.NewLine))
    添加(item.url);
    其他的
    invalidURL.Add(urlist.Count);
    }
    }
    }
    

您也可以使用Windows SDK附带的XSD.exe工具执行此操作。

我假设您正在阅读有效的xml文档,如myFile.xml。我还假设“url”是您要获取的元素

将文档加载到XMLDocument类中,并使用该类遍历节点。这将消除错误字符,因为它将这些字符转换为正确的格式,如&将转换为amp;etc

下面的方法在给出您提供的示例时应该有效

        //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;
    }
//将文件文本转换为字符串
System.IO.StreamReader sr=new System.IO.StreamReader(@“C:\test.xml”);
字符串xmlText=sr.ReadToEnd();
高级关闭();
//创建字符串列表并调用该方法
列表URL=readXMLDoc(xmlText);
//看看我们有没有名单
如果(URL!=null)
{
//干坏事
}
私有列表readXMLDoc(字符串文件文本)
{
//创建一个字符串列表来保存我们的URL
List urlList=新列表();
尝试
{
//克雷亚
        //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;
    }