我永远不能predict XMLReader的行为。在了解任何提示? [英] I can never predict XMLReader behavior. Any tips on understanding?

查看:171
本文介绍了我永远不能predict XMLReader的行为。在了解任何提示?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好像每次我使用一个XMLReader时间,我结束了一堆反复试验试图找出什么,我要读对我所读对我刚才读。我总是搞清楚到底,但我还是用它无数次之后,似乎并没有牢牢把握什么一个XMLReader实际上是在做当我打电话的各种功能。例如,当我打电话阅读的第一次,如果读取一个元素的开始标记,是现在的元素标签的末尾,或者准备开始读元素的属性?是否知道属性的值,但如果我叫的getAttribute?会发生什么,如果我叫ReadStartElement在这一点?将它读完开始元素,或查找下一个,跳过所有的属性?如果我想读一些元素 - 什么是尝试读取下一个元素,并确定它的名称是最好的方式。将读其次则isStartElement工作,还是我刚才读的元素之后会则isStartElement在返回有关节点的信息?

It seems every time I use an XMLReader, I end up with a bunch of trial and error trying to figure out what I'm about to read versus what I'm reading versus what I just read. I always figure it out in the end, but I still, after using it numerous times, don't seem to have a firm grasp of what an XMLReader is actually doing when I call the various functions. For example, when I call Read the first time, if it reads an element start tag, is it now at the end of the element tag, or ready to begin reading the element's attributes? Does it know the values of the attributes yet if I call GetAttribute? What will happen if I call ReadStartElement at this point? Will it finish reading the start element, or look for the next one, skipping all the attributes? What if I want to read a number of elements -- what's the best way to try to read the next element and determine what its name is. Will Read followed by IsStartElement work, or will IsStartElement be returning information about the node following the element I just read?

正如你所看到的我真的很缺乏的,其中一个XMLReader是在其阅读和如何将其状态受各种读取功能的各个阶段的理解。有一些简单的图案,我已经根本没有注意到吗?

As you can see I really am lacking an understanding of where an XMLReader is at during the various phases of its reading and how its state is affected by various read functions. Is there some simple pattern that I've simply failed to notice?

下面是(从反应采取)问题的另一个例子:

Here's another example of the problem (taken from the responses):

string input = "<machine code=\"01\">The Terminator" +
   "<part code=\"01a\">Right Arm</part>" +
   "<part code=\"02\">Left Arm</part>" +
   "<part code=\"03\">Big Toe</part>" +
   "</machine>";

using (System.IO.StringReader sr = new System.IO.StringReader(input))
{
   using (XmlTextReader reader = new XmlTextReader(sr))
   {
      reader.WhitespaceHandling = WhitespaceHandling.None;
      reader.MoveToContent();

      while(reader.Read())
      {
         if (reader.Name.Equals("machine") && (reader.NodeType == XmlNodeType.Element))
         {
            Console.Write("Machine code {0}: ", reader.GetAttribute("code"));
            Console.WriteLine(reader.ReadElementString("machine"));
         }
         if(reader.Name.Equals("part") && (reader.NodeType == XmlNodeType.Element))
         {
            Console.Write("Part code {0}: ", reader.GetAttribute("code"));
            Console.WriteLine(reader.ReadElementString("part"));
         }
      }
   }
}

第一个问题,设备的节点被完全跳过。 MoveToContent似乎移动到机器元素的含量导致它从未被解析。此外,如果你跳过MoveToContent,你会得到一个错误:'元素'是无效XmlNodeType。试图ReadElementString,我不能完全解释。

First problem, the machine node is skipped completely. MoveToContent seems to move to the content of the machine element causing it to never be parsed. Furthermore, if you skip MoveToContent, you get an error: "'Element' is an invalid XmlNodeType." trying to ReadElementString, which I can't quite explain.

接下来的问题是,在读取第一部分元件,ReadElementString似乎阅读后以定位读者在下一部分元件的开头。这将导致reader.Read在下一循环的开始跳过下一部分元素权利跳到最后部分元件。所以这个code中的最终输出是:

Next problem is, while reading the first part element, ReadElementString seems to position the reader at the beginning of the next part element after reading. This causes the reader.Read at the beginning of the next loop to skip over the next part element jumping right to the last part element. So the final output of this code is:

部分code 01A:右臂

Part code 01a: Right Arm

部分code 03:大脚趾

Part code 03: Big Toe

这是XMLReader的那我想了解confusign行为的一个最好的例子。

This is a prime example of the confusign behavior of XMLReader that I'm trying to understand.

推荐答案

我的最新解决方案(这适用于我目前的情况下)是实现状态机读(),则isStartElement(名称)和的getAttribute(名称)要坚持

My latest solution (which works for my current case) is to stick with Read(), IsStartElement(name) and GetAttribute(name) in implementing a state machine.

using (System.Xml.XmlReader xr = System.Xml.XmlTextReader.Create(stm))
{
   employeeSchedules = new Dictionary<string, EmployeeSchedule>();
   EmployeeSchedule emp = null;
   WeekSchedule sch = null;
   TimeRanges ranges = null;
   TimeRange range = null;
   while (xr.Read())
   {
      if (xr.IsStartElement("Employee"))
      {
         emp = new EmployeeSchedule();
         employeeSchedules.Add(xr.GetAttribute("Name"), emp);
      }
      else if (xr.IsStartElement("Unavailable"))
      {
         sch = new WeekSchedule();
         emp.unavailable = sch;
      }
      else if (xr.IsStartElement("Scheduled"))
      {
         sch = new WeekSchedule();
         emp.scheduled = sch;
      }
      else if (xr.IsStartElement("DaySchedule"))
      {
         ranges = new TimeRanges();
         sch.daySchedule[int.Parse(xr.GetAttribute("DayNumber"))] = ranges;
         ranges.Color = ParseColor(xr.GetAttribute("Color"));
         ranges.FillStyle = (System.Drawing.Drawing2D.HatchStyle)
            System.Enum.Parse(typeof(System.Drawing.Drawing2D.HatchStyle),
            xr.GetAttribute("Pattern"));
      }
      else if (xr.IsStartElement("TimeRange"))
      {
         range = new TimeRange(
            System.Xml.XmlConvert.ToDateTime(xr.GetAttribute("Start"),
            System.Xml.XmlDateTimeSerializationMode.Unspecified),
            new TimeSpan((long)(System.Xml.XmlConvert.ToDouble(xr.GetAttribute("Length")) * TimeSpan.TicksPerHour)));
         ranges.Add(range);
      }
   }
   xr.Close();
}

在读,则isStartElement将返回true,如果你只是读一开始元素(optinally检查元素读的名称),并可以立即访问该元素的所有属性。如果你所需要阅读的元素和属性,这是pretty的简单。

After Read, IsStartElement will return true if you just read a start element (optinally checking the name of the element read), and you can access all the attributes of that element immediately. If all you need to read is elements and attributes, this is pretty straightforward.

修改 新的例子张贴在的问题提出了一些其他方面的挑战。来读取XML的正确方法似乎是这样的:

Edit The new example posted in the question poses some other challenges. The correct way to read that XML seems to be like this:

using (System.IO.StringReader sr = new System.IO.StringReader(input))
{
   using (XmlTextReader reader = new XmlTextReader(sr))
   {
      reader.WhitespaceHandling = WhitespaceHandling.None;

      while(reader.Read())
      {
         if (reader.Name.Equals("machine") && (reader.NodeType == XmlNodeType.Element))
         {
            Console.Write("Machine code {0}: ", reader.GetAttribute("code"));
            Console.WriteLine(reader.ReadString());
         }
         if(reader.Name.Equals("part") && (reader.NodeType == XmlNodeType.Element))
         {
            Console.Write("Part code {0}: ", reader.GetAttribute("code"));
            Console.WriteLine(reader.ReadString());
         }
      }
   }
}

您必须使用ReadString代替ReadElementString为了避免读取端元件并跳过插入下一个元素的起点(让下面的读()跳过端元件,因此它不会跳过下一开始元件)。不过这似乎有些混乱和不可靠的,但它适用于这种情况。

You have to use ReadString instead of ReadElementString in order to avoid reading the end element and skipping into the beginning of the next element (let the following Read() skip over the end element so it doesn't skip over the next start element). Still this seems somewhat confusing and potentially unreliable, but it works for this case.

在一些额外的思想,我的看法是,XMLReader就太混乱,如果的你用任何方法来读取比Read方法等内容的。我认为这是非常简单的,如果你把自己定格Read方法从XML流中读取。下面是它如何工作的新的例子(再次,似乎则isStartElement,的getAttribute和阅读是关键的方法,你最终会得到一个状态机):

After some additional thought, my opinion is that XMLReader is just too confusing if you use any methods to read content other than the Read method. I think it's much simpler if you confine yourself to the Read method to read from the XML stream. Here's how it would work with the new example (once again, it seems IsStartElement, GetAttribute and Read are the key methods, and you end up with a state machine):

while(reader.Read())
{
   if (reader.IsStartElement("machine"))
   {
      Console.Write("Machine code {0}: ", reader.GetAttribute("code"));
   }
   if(reader.IsStartElement("part"))
   {
      Console.Write("Part code {0}: ", reader.GetAttribute("code"));
   }
   if (reader.NodeType == XmlNodeType.Text)
   {
      Console.WriteLine(reader.Value);
   }
}

这篇关于我永远不能predict XMLReader的行为。在了解任何提示?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆