我一直在编写XML并阅读它时遇到了问题。我有一个手写的XML可以很好地阅读,但是在我编写XML之后它很有趣。
WriteXML的输出:http://www.craigmouser.com/random/test.xml
如果你在(特价)标签后按Enter键,它会起作用。 I.E.使(特价)(特别)看起来像
(特价)
(特殊)
如果我单步执行它,在读取它时,它将转到特殊的开始节点,然后下一次迭代将其作为名为Shots的EndElement读取。我不知道从哪里开始。提前谢谢。
代码:写作
public void SaveXMLFile(string filename, Bar b, Boolean saveOldData)
{
XmlWriter xml;
if(filename.Contains(".xml"))
{
xml = XmlWriter.Create(filename);
}
else
{
xml = XmlWriter.Create(filename + ".xml");
}
xml.WriteStartElement("AggievilleBar");
xml.WriteElementString("name", b.Name);
xml.WriteStartElement("picture");
xml.WriteAttributeString("version", b.PictureVersion.ToString());
xml.WriteEndElement();
xml.WriteElementString("location", b.Location.Replace(Environment.NewLine, "\n"));
xml.WriteElementString("news", b.News.Replace(Environment.NewLine, "\n"));
xml.WriteElementString("description", b.Description.Replace(Environment.NewLine, "\n"));
xml.WriteStartElement("specials");
xml.WriteString("\n"); //This line fixes the problem... ?!?!
foreach (Special s in b.Specials)
{
if (s.DayOfWeek > 0 || (s.DayOfWeek == -1
&& ((s.Date.CompareTo(DateTime.Today) < 0 && saveOldData )
|| s.Date.CompareTo(DateTime.Today) >= 0)))
{
xml.WriteStartElement("special");
xml.WriteAttributeString("dayofweek", s.DayOfWeek.ToString());
if (s.DayOfWeek == -1)
xml.WriteAttributeString("date", s.Date.ToString("yyyy-MM-dd"));
xml.WriteAttributeString("price", s.Price.ToString());
xml.WriteString(s.Name);
xml.WriteEndElement();
}
}
xml.WriteEndElement();
xml.WriteEndElement();
xml.Close();
}
代码:阅读
public Bar LoadXMLFile(string filename)
{
List<Special> specials = new List<Special>();
XmlReader xml;
try
{
xml = XmlReader.Create(filename);
}
catch (Exception)
{
MessageBox.Show("Unable to open file. If you get this error upon opening the program, we failed to pull down your current data. You will most likely be unable to save, but you are free to try. If this problem persists please contact us at pulsarproductionssupport@gmail.com",
"Error Opening File", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
Bar current = new Bar();
Special s = new Special();
while (xml.Read())
{
if (xml.IsStartElement())
{
switch (xml.Name)
{
case "AggievilleBar":
current = new Bar();
break;
case "name":
if (xml.Read())
current.Name = xml.Value.Trim();
break;
case "picture":
if (xml.HasAttributes)
{
try
{
current.PictureVersion = Int32.Parse(xml.GetAttribute("version"));
}
catch (Exception)
{
MessageBox.Show("Error reading in the Picture Version Number.","Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
}
}
break;
case "location":
if (xml.Read())
current.Location = xml.Value.Trim();
break;
case "news":
if (xml.Read())
current.News = xml.Value.Trim();
break;
case "description":
if (xml.Read())
current.Description = xml.Value.Trim();
break;
case "specials":
if (xml.Read())
specials = new List<Special>();
break;
case "special":
s = new Special();
if (xml.HasAttributes)
{
try
{
s.DayOfWeek = Int32.Parse(xml.GetAttribute(0));
if (s.DayOfWeek == -1)
{
s.Date = DateTime.Parse(xml.GetAttribute(1));
s.Price = Int32.Parse(xml.GetAttribute(2));
}
else
s.Price = Int32.Parse(xml.GetAttribute(1));
}
catch (Exception)
{
MessageBox.Show("Error reading in a special.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
if (xml.Read())
s.Name = xml.Value.Trim();
break;
}
}
else
{
switch (xml.Name)
{
case "AggievilleBar":
xml.Close();
break;
case "special":
specials.Add(s);
break;
case "specials":
current.Specials = specials;
break;
}
}
}
return current;
}
答案 0 :(得分:1)
如果没有看到您的代码,很难真正直接回答这个问题。但是,我可以建议使用Linq-to-XML而不是XMLReader / XMLWriter - 当您不必一次读取每个节点并确定您正在使用哪个节点时,使用它会更容易。听起来像你遇到的问题。
例如,代码如下:
using (var reader = new XmlReader(...))
{
while reader.Read()
{
if (reader.Name = "book" && reader.IsStartElement)
{
// endless, confusing nesting!!!
}
}
}
变为:
var elem = doc.Descendants("book").Descendants("title")
.Where(c => c.Attribute("name").Value == "C# Basics")
.FirstOrDefault();
有关LINQ-to-XML的介绍,请查看http://www.c-sharpcorner.com/UploadFile/shakthee/2868/,或者只搜索“Linq-to-XML”。那里有很多例子。
修改:我尝试了您的代码,我能够重现您的问题。似乎在special
标记之前没有换行符时,第一个special
元素会被读入IsStartElement() == false
。我不确定为什么会这样;甚至在XML Specifications中浏览过,并且在元素之前没有看到有关换行符的任何要求。
我用Linq-to-XML重写了你的代码,它没有任何换行符就可以正常工作:
var xdoc = XDocument.Load(filename);
var barElement = xdoc.Element("AggievilleBar");
var specialElements = barElement.Descendants("special").ToList();
var specials = new List<Special>();
specialElements.ForEach(s =>
{
var dayOfWeek = Convert.ToInt32(s.Attribute("dayofweek").Value);
var price = Convert.ToInt32(s.Attribute("price").Value);
var date = s.Attribute("date");
specials.Add(new Special
{
Name = s.Value,
DayOfWeek = dayOfWeek,
Price = price,
Date = date != null ? DateTime.Parse(date.Value) : DateTime.MinValue
});
});
var bar = new Bar() {
Name = barElement.Element("name").Value,
PictureVersion = Convert.ToInt32(barElement.Elements("picture").Single()
.Attribute("version").Value),
Location = barElement.Element("location").Value,
Description = barElement.Element("description").Value,
News = barElement.Element("news").Value,
Specials = specials
};
return bar;
您是否考虑使用Linq-to-XML而不是XMLReader?我过去曾经遇到过与XMLReader有关的麻烦,一旦我切换到Linq-to-XML就没有回头了!
编辑:我知道这个问题现在已经很老了,但我刚刚看到一篇文章让我想起了这个问题并且可能解释了为什么会这样: - &gt; http://www.codeproject.com/KB/dotnet/pitfalls_xml_4_0.aspx
作者声明:
从这个角度来看,XmlReaders / Writers和XDocument之间的一个令人讨厌的区别是处理空格的方式。 (见http://msdn.microsoft.com/en-us/library/bb387014.aspx。)
来自msdn:
在大多数情况下,如果方法将LoadOptions作为参数,则可以选择将无关紧要的空格保留为XML树中的文本节点。但是,如果方法从XmlReader加载XML,则XmlReader将确定是否保留空白。设置PreserveWhitespace将无效。
所以也许,因为你正在使用XmlReader加载,所以XmlReader正在确定它是否应该保留空白区域。最有可能的是它保留了空白区域,这就是新线(或缺少线条)产生影响的原因。只要您使用XmlReader,似乎您无法做任何改变它的事情!非常特别。
答案 1 :(得分:1)
我建议您使用XmlDocument
类及其Load
和Save
方法,然后使用XML树而不是弄乱XmlReader
和{ {1}}。根据我使用XmlWriter
的经验,可以减少奇怪的格式问题。