我的最新解决方案(适用于我当前的情况)是在实现状态机时坚持使用Read()、isstartement(name)和GetAttribute(name)。
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,并且您可以立即访问该元素的所有属性。如果您只需要阅读元素和属性,那么这非常简单。
编辑
问题中的新例子提出了一些其他挑战。读取该XML的正确方法如下所示:
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());
}
}
}
}
经过一些额外的思考,我的观点是XMLReader太令人困惑了
如果
您可以使用read方法以外的任何方法来读取内容。我认为,如果您只使用Read方法来读取XML流,那么会简单得多。下面是它在新示例中的工作方式(再次说明,IsStartElement、GetAttribute和Read似乎是关键方法,您最终得到的是一个状态机):
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);
}
}