c# - XmlReader ReadStartElement 导致 XmlException

标签 c# .net silverlight xmlreader xmlexception

我正在 Silverlight 项目中使用 XmlReader 编写文件阅读器。但是,我遇到了一些错误(特别是关于 XmlReader.ReadStartElement 方法),这让我相信我误解了如何在整个过程中的某个地方使用它。

基本上,这是我正在使用的 Xml 格式的示例:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<root>
    <EmptyElement />
    <NonEmptyElement Name="NonEmptyElement">
        <SubElement Name="SubElement" />
    </NonEmptyElement>
</root>

下面是一些代码示例,使用方式与我的使用方式相同:

public void ReadData(XmlReader reader)
{
    // Move to root element
    reader.ReadStartElement("root");

    // Move to the empty element
    reader.ReadStartElement("EmptyElement");

    // Read any children
    while(reader.ReadToNextSibling("SubEmptyElement"))
    {
        // ...
    }

    // Read the end of the empty element
    reader.ReadEndElement();

    // Move to the non empty element
    reader.ReadStartElement("NonEmptyElement");    // NOTE: This is where I get the error.

    // ...
}

因此,从本质上讲,我只是试图读取每个元素和任何包含的子元素。我在突出显示的地方得到的错误如下:

错误描述

[Xml_InvalidNodeType] Arguments: None,10,8 Debugging resource strings are unavailable. Often the key and arguments provide sufficient information to diagnose the problem. See http://go.microsoft.com/fwlink/?linkid=106663&Version=4.0.51204.0&File=System.Xml.dll&Key=Xml_InvalidNodeType

错误堆栈跟踪

at System.Xml.XmlReader.ReadStartElement(String name) at ----------------

如有任何建议或指导,我们将不胜感激。

编辑 由于此读取器需要相当通用,因此可以假定 Xml 可能包含作为 EmptyElement 的子元素的元素。因此,尝试读取任何 SubEmptyElements 应该是有效的。

最佳答案

<SubElement/>不是 <EmptyElement> 的 sibling , 所以 <NonEmptyElement>将被完全跳过,您调用 ReadEndElement()将读取结束元素 </root> .当您尝试随后读取“NonEmptyElement”时,没有剩余元素,您将得到一个 XmlException:{“'None' 是一个无效的 XmlNodeType。第 8 行,位置 1。”}

另请注意,由于 <EmptyElement/>为空,当您 ReadStartElement("EmptyElement") 时,您将读取整个元素,并且您不需要使用 ReadEndElement()。

我还建议您将阅读器设置配置为 IgnoreWhitespace(如果您尚未这样做),以避免在您不期望的情况下读取(无关紧要的)空白文本节点而引入的任何复杂情况。

尝试将 NonEmptyElement 的读取上移:

public static void ReadData(XmlReader reader)
{
    reader.ReadStartElement("root");

    reader.ReadStartElement("EmptyElement");

    reader.ReadStartElement("NonEmptyElement");

    while (reader.ReadToNextSibling("SubEmptyElement"))
    {
        // ...
    }

    reader.ReadEndElement(/* NonEmptyElement */);

    reader.ReadEndElement(/* root */);
    // ...
}

如果你只是想跳过 <EmptyElement> 中的任何内容,无论它是否实际为空,使用 ReadToFollowing :

public static void ReadData(XmlReader reader)
{
    reader.ReadStartElement("root");

    reader.ReadToFollowing("NonEmptyElement");

    Console.WriteLine(reader.GetAttribute("Name"));

    reader.ReadStartElement("NonEmptyElement");

    Console.WriteLine(reader.GetAttribute("Name"));
    while (reader.ReadToNextSibling("SubEmptyElement"))
    {
        // ...
    }

    reader.ReadEndElement(/* NonEmptyElement */);

    reader.ReadEndElement(/* root */);
    // ...
}

更新:这是一个更完整的示例,具有更清晰的数据模型。也许这更接近您的要求。

XML文件1.xml:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<root>
  <Person Type="Homeless"/>
  <Person Type="Developer">
    <Home Type="Apartment" />
  </Person>
  <Person Type="Banker">
    <Home Type="Apartment"/>
    <Home Type="Detached"/>
    <Home Type="Mansion">
      <PoolHouse/>
    </Home>
  </Person>
</root>

程序.cs:

using System;
using System.Xml;

namespace ConsoleApplication6
{
    internal class Program
    {
        public static void ReadData(XmlReader reader)
        {
            reader.ReadStartElement("root");

            while (reader.IsStartElement("Person"))
            {
                ReadPerson(reader);
            }

            reader.ReadEndElement( /* root */);
        }

        public static void ReadPerson(XmlReader reader)
        {
            Console.WriteLine(reader.GetAttribute("Type"));
            bool isEmpty = reader.IsEmptyElement;
            reader.ReadStartElement("Person");
            while (reader.IsStartElement("Home"))
            {
                ReadHome(reader);
            }
            if (!isEmpty)
            {
                reader.ReadEndElement( /* Person */);
            }
        }

        public static void ReadHome(XmlReader reader)
        {
            Console.WriteLine("\t" + reader.GetAttribute("Type"));
            bool isEmpty = reader.IsEmptyElement;
            reader.ReadStartElement("Home");

            if (!isEmpty)
            {
                reader.Skip();
                reader.ReadEndElement( /* Home */);
            }
        }

        private static void Main(string[] args)
        {
            var settings = new XmlReaderSettings { IgnoreWhitespace = true };
            using (var xr = XmlReader.Create("XMLFile1.xml", settings))
            {
                ReadData(xr);
            }
            Console.ReadKey();
        }
    }
}

关于c# - XmlReader ReadStartElement 导致 XmlException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4982251/

相关文章:

c# - 如何获取系统日期时间格式?

.net - ComponentOne 3D 表面贴图图表的替代品

silverlight - 将代码保留在 XAML 代码之外的真正优势是什么?

wpf - 如何将嵌套在类中的枚举分配给 XAML 属性?

silverlight - INotifyDataErrorInfo.GetErrors(null) 应该返回所有错误吗?

C# MVVM 升级到 EF5 - 实体成员函数去哪儿了?

c# - 无法使用 NetMQ 4.x 使 ReadyReceive pub-sub 工作

c# - NHibernate 不插入 child

.net - 尝试将灰度图像写入 VideoWriter 时 EMGU 崩溃

c# - 导出事件日志时出现异常