XmlReader的ReadStartElement导致XmlExceptionXmlReader、ReadStartElement、XmlException

2023-09-05 00:00:05 作者:我不敢喝雪碧我怕透心凉√

我正在写使用的XmlReader在Silverlight项目中的文件阅读器。不过,我得到了一些错误(特别是围绕XmlReader.ReadStartElement法),它使我相信,我误解了怎样的地方使用它前进的道路。

I'm writing a file reader using the XmlReader in a Silverlight project. However, I'm getting some errors (specifically around the XmlReader.ReadStartElement method) and it's causing me to believe that I've misunderstood how to use it somewhere along the way.

基本上,这里是我使用的XML的格式样本:

Basically, here is a sample of the format of the Xml I am using:

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

在这里是用同样的方式使用了一些code因为我是如何使用它的示例:

And here is a sample of some code used in the same way as how I am using it:

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.

    // ...
}

因此​​,从本质上讲,我只是想读的每个元素和任何含有儿童。我得到的强调点的错误如下:

So, essentially, I am simply trying to read each element and any contained children. The error I get at the highlighted point is as follows:

错误说明

[Xml_InvalidNodeType]   参数:无,10,8   调试资源字符串不可用。通常情况下,密钥和参数提供足够的信息来诊断问题。请参阅http://go.microsoft.com/fwlink/?linkid=106663&Version=4.0.51204.0&File=System.Xml.dll&Key=Xml_InvalidNodeType

[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

错误堆栈跟踪

在System.Xml.XmlReader.ReadStartElement(字符串名称)      在----------------

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

在此的任何意见或方向将大大AP preciated。

Any advice or direction on this would be greatly appreciated.

修改 由于该读者需要相当通用的,它可以假定在Xml可能包含与所述EmptyElement的子元素。因此,在读取任何SubEmptyElements的尝试应该是有效的。

EDIT Since this reader needs to be fairly generic, it can be assumed that the Xml may contain elements that are children of the EmptyElement. As such, the attempt at reading any SubEmptyElements should be valid.

推荐答案

&LT;子元件/&GT; 不是℃的兄弟姐妹; EmptyElement&GT ; ,所以&LT; NonEmptyElement&GT; 是会得到完全跳过,并且 ReadEndElement您的来电()将读取结束元素&LT; /根&GT; 。当您尝试后来改为NonEmptyElement,没有离开的元素,你会得到一个XmlException:{无是无效的XmlNodeType 8号线​​,1位。}

<SubElement/> is not a sibling of <EmptyElement>, so <NonEmptyElement> is going to get skipped entirely, and your call to ReadEndElement() will read the end element </root>. When you try to subsequently read "NonEmptyElement", there are no elements left, and you'll get an XmlException: {"'None' is an invalid XmlNodeType. Line 8, position 1."}

还要注意的是,因为&LT; EmptyElement /&GT; 是空的,当你ReadStartElement(EmptyElement),你会阅读整个元素,你赢了吨需要使用ReadEndElement()。

Note also that since <EmptyElement/> is empty, when you ReadStartElement("EmptyElement"), you'll read the whole element, and you won't need to use ReadEndElement().

我也想建议您配置阅读器的设置,以IgnoreWhitespace(如果你没有这样做),以避免出台任何并发症通过阅读,当你不希望他们(不显着)空白文本节点。

I'd also recommend that you configure your reader settings to IgnoreWhitespace (if you're not already doing so), to avoid any complications introduced by reading (insignificant) whitespace text nodes when you aren't expecting them.

尝试移动NonEmptyElement的读了起来:

Try moving the Read of NonEmptyElement up:

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 */);
    // ...
}

如果你只是想跳过&LT任何东西; EmptyElement&GT; ,无论其是否真正为空,使用 ReadToFollowing

If you just want to skip anything in <EmptyElement>, regardless of whether or not its actually empty, use 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 */);
    // ...
}

更新:这里有一个更清晰的数据模型更全面的例子。也许这是更接近你的要求是什么。

Update: Here's a fuller example with a clearer data model. Maybe this is closer to what you're asking for.

XMLFile1.xml:

XMLFile1.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>

Program.cs的:

Program.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();
        }
    }
}