奇怪的未处理的XmlException行为

时间:2009-09-10 11:34:47

标签: c# xml exception

在阅读有关未处理的XmlException的this recent question时,我尝试在.NET 2.0和3.5控制台应用程序中重现它。

但是在我的代码中,它的行为完全符合预期,XmlDocument.Load方法抛出XmlException,因为源xml文件包含NULL字符。

那么,为什么以下代码中的Load语句(来自该示例),不抛出XmlException?更重要的是,为什么围绕SelectNodes()方法调用的有效try块不处理XmlException?

虽然我猜测内部可能存在某种延迟加载/缓存,但这种行为是不是非常不直观且令人困惑?

(之前的问题清楚地显示了调试器的屏幕截图,抱怨SelectNodes()抛出了一个XmlException,但它未被处理???)

    XmlDocument xDoc = new XmlDocument();
    xDoc.Load(File.FullName);

    //work through each print batch in this queue file
    try
    {
        // This line throws an XmlException but is not handled by the catch!
        XmlNodeList nodeList = xDoc.SelectNodes("Reports/PrintBatch");

        foreach (XmlNode printBatch in nodeList)//xDoc.SelectNodes("Reports/PrintBatch"))
        {
            PrintBatch batch = new PrintBatch();
            batch.LoadBatch(printBatch, File.Extension);
            this.AddBatch(batch);
        }
    }
    catch (XmlException e)
    {
        //this report had an error loading!
        Console.WriteLine(e.Message);
    }

2 个答案:

答案 0 :(得分:2)

XmlDocument.Load始终按预期抛出异常。

只是有时调试器得到错误的行号。根据我的经验,下一行代码错误地被突出显示为异常的抛出者并不罕见。

您可以在屏幕截图中看到:ASP错误页面正确显示XmlDocument.Load是thrower,而不是SelectNodes语句。

答案 1 :(得分:1)

可能有很多原因导致异常而非异常,这很可能与NULL字符的位置有关。根据他的堆栈,他的Null字符似乎位于XML的末尾,位于115227位。可能是它之前的文本只是有效的XML,并且意外地将一个额外的NULL字符添加到文件的末尾。你在哪里有NULL字符?

或者,他的NULL字符位于属性或元素内,并被视为文本的一部分。它还可能取决于XML是UTF-8,UTF-16或其他编码类型。有太多的变量需要考虑。


当NULL字符在最后时,整个文件恰好是一个漂亮的,以null结尾的字符串。不过,正如你所说的那样,奇怪的是它被认为是一个未处理的异常,而它位于try-except块内...

关于捕获未处理的异常有一些interesting reading here,但它并不能解释它们为什么会发生。

但是,如果我不得不猜测......在XML类的后面有一堆非托管代码。由于NULL字符,这个非托管代码会变得混乱,并在发布时产生错误。对SelectNodes()的调用将触发验证并发现错误,因此它被引发。系统开始处理异常处理程序,但它首先尝试释放xDoc,因为它不在异常块内部或之后使用。这释放了非托管代码,但是非托管代码仍然混淆,因此它再次引发异常。这会阻止Catch处理异常。 您可以通过在Catch语句之后添加第二个xDoc.Load()来测试这一点,这将阻止在Catch之前释放xDoc。

尽管如此,这只是猜测......对我来说似乎是一个.NET错误。