我如何在C#中构建XML?

我怎样才能在C#中生成有效的XML?

这取决于场景。 XmlSerializer肯定是一种方法,并具有直接映射到对象模型的优势。 在.NET 3.5中, XDocument等也非常友好。 如果尺寸非常大,那么XmlWriter就是你的朋友。

对于XDocument示例:

 Console.WriteLine( new XElement("Foo", new XAttribute("Bar", "some & value"), new XElement("Nested", "data"))); 

或者与XmlDocument相同:

 XmlDocument doc = new XmlDocument(); XmlElement el = (XmlElement)doc.AppendChild(doc.CreateElement("Foo")); el.SetAttribute("Bar", "some & value"); el.AppendChild(doc.CreateElement("Nested")).InnerText = "data"; Console.WriteLine(doc.OuterXml); 

如果您正在编写大量的数据流,那么任何DOM方法(如XmlDocument / XDocument等)都将很快占用大量内存。 所以,如果你正在从CSV写一个100 MB的XML文件,你可能会考虑XmlWriter ; 这是更原始的(一次写入式的流水线),但非常有效(想象一个大循环):

 XmlWriter writer = XmlWriter.Create(Console.Out); writer.WriteStartElement("Foo"); writer.WriteAttributeString("Bar", "Some & value"); writer.WriteElementString("Nested", "data"); writer.WriteEndElement(); 

最后,通过XmlSerializer

 [Serializable] public class Foo { [XmlAttribute] public string Bar { get; set; } public string Nested { get; set; } } ... Foo foo = new Foo { Bar = "some & value", Nested = "data" }; new XmlSerializer(typeof(Foo)).Serialize(Console.Out, foo); 

这是映射到类的一个很好的模型,等等。 然而,如果你正在做一些简单的事情(或者如果所需的XML与对象模型没有真正的直接关系),这可能是过度的。 XmlSerializer另一个问题是它不喜欢序列化不可变的类型:每个东西都必须有一个公共的getter setter(除非你自己通过实现IXmlSerializable ,在这种情况下,你没有通过使用XmlSerializer获得很多)。

我已经尝试过的最好的事情是LINQ to XSD (这是大多数开发人员不知道的)。 你给它一个XSD Schema,它会在后台为你生成一个完美映射的完整的强类型对象模型(基于LINQ to XML),这真的很容易处理 – 它更新并验证你的对象模型和XML即时的。 虽然它仍然是“预览”,我还没有遇到任何错误。

如果您有一个如下所示的XSD架构:

  <xs:element name="RootElement"> <xs:complexType> <xs:sequence> <xs:element name="Element1" type="xs:string" /> <xs:element name="Element2" type="xs:string" /> </xs:sequence> <xs:attribute name="Attribute1" type="xs:integer" use="optional" /> <xs:attribute name="Attribute2" type="xs:boolean" use="required" /> </xs:complexType> </xs:element> 

然后你可以简单地构建这样的XML:

 RootElement rootElement = new RootElement; rootElement.Element1 = "Element1"; rootElement.Element2 = "Element2"; rootElement.Attribute1 = 5; rootElement.Attribute2 = true; 

或者像这样简单地从文件中加载一个XML:

 RootElement rootElement = RootElement.Load(filePath); 

或者像这样保存:

 rootElement.Save(string); rootElement.Save(textWriter); rootElement.Save(xmlWriter); 

rootElement.Untyped也产生XElement形式的元素(从LINQ到XML)。

 new XElement("Foo", from s in nameValuePairList select new XElement("Bar", new XAttribute("SomeAttr", "SomeAttrValue"), new XElement("Name", s.Name), new XElement("Value", s.Value) ) ); 

我会给XLINQ(阅读:LINQ to XML)一试。 这很容易,直观,很容易编辑。

示例: 使用XLinq读取和写入XML

还可以看看Mark S. Rasmussen的XmlDocument流畅接口 ,它实际上提供了简单的输入/读取XML输出。

XmlWriter是编写优秀XML的最快方式。 XDocument,XMLDocument和其他一些工作正常,但没有优化编写XML。 如果你想尽可能快地写XML,你应该使用XmlWriter。

在过去,我已经创建了我的XML Schema,然后使用一个工具来生成C#类,它将序列化到该模式。 XML模式定义工具就是一个例子

http://msdn.microsoft.com/en-us/library/x6c1kb0s(VS.71).aspx

我认为这个资源应该足以适度的XML保存/加载: 使用C#读/写XML 。

我的任务是存储音乐符号。 我选择XML,因为我猜.NET已经足够成熟,可以轻松解决任务。 我是对的 :)

这是我的歌曲文件原型:

 <music judul="Kupu-Kupu yang Lucu" pengarang="Ibu Sud" tempo="120" birama="4/4" nadadasar="1=F" biramapembilang="4" biramapenyebut="4"> <not angka="1" oktaf="0" naikturun="" nilai="1"/> <not angka="2" oktaf="0" naikturun="" nilai="0.5"/> <not angka="5" oktaf="1" naikturun="/" nilai="0.25"/> <not angka="2" oktaf="0" naikturun="\" nilai="0.125"/> <not angka="1" oktaf="0" naikturun="" nilai="0.0625"/> </music> 

这可以很容易地解决:

保存到文件:

  private void saveToolStripMenuItem_Click(object sender, EventArgs e) { saveFileDialog1.Title = "Save Song File"; saveFileDialog1.Filter = "Song Files|*.xsong"; if (saveFileDialog1.ShowDialog() == DialogResult.OK) { FileStream fs = new FileStream(saveFileDialog1.FileName, FileMode.Create); XmlTextWriter w = new XmlTextWriter(fs, Encoding.UTF8); w.WriteStartDocument(); w.WriteStartElement("music"); w.WriteAttributeString("judul", Program.music.getTitle()); w.WriteAttributeString("pengarang", Program.music.getAuthor()); w.WriteAttributeString("tempo", Program.music.getTempo()+""); w.WriteAttributeString("birama", Program.music.getBirama()); w.WriteAttributeString("nadadasar", Program.music.getNadaDasar()); w.WriteAttributeString("biramapembilang", Program.music.getBiramaPembilang()+""); w.WriteAttributeString("biramapenyebut", Program.music.getBiramaPenyebut()+""); for (int i = 0; i < listNotasi.Count; i++) { CNot not = listNotasi[i]; w.WriteStartElement("not"); w.WriteAttributeString("angka", not.getNot() + ""); w.WriteAttributeString("oktaf", not.getOktaf() + ""); String naikturun=""; if(not.isTurunSetengah())naikturun="\\"; else if(not.isNaikSetengah())naikturun="/"; w.WriteAttributeString("naikturun",naikturun); w.WriteAttributeString("nilai", not.getNilaiNot()+""); w.WriteEndElement(); } w.WriteEndElement(); w.Flush(); fs.Close(); } } 

对于加载文件:

 openFileDialog1.Title = "Open Song File"; openFileDialog1.Filter = "Song Files|*.xsong"; if (openFileDialog1.ShowDialog() == DialogResult.OK) { FileStream fs = new FileStream(openFileDialog1.FileName, FileMode.Open); XmlTextReader r = new XmlTextReader(fs); while (r.Read()) { if (r.NodeType == XmlNodeType.Element) { if (r.Name.ToLower().Equals("music")) { Program.music = new CMusic(r.GetAttribute("judul"), r.GetAttribute("pengarang"), r.GetAttribute("birama"), Convert.ToInt32(r.GetAttribute("tempo")), r.GetAttribute("nadadasar"), Convert.ToInt32(r.GetAttribute("biramapembilang")), Convert.ToInt32(r.GetAttribute("biramapenyebut"))); } else if (r.Name.ToLower().Equals("not")) { CNot not = new CNot(Convert.ToInt32(r.GetAttribute("angka")), Convert.ToInt32(r.GetAttribute("oktaf"))); if (r.GetAttribute("naikturun").Equals("/")) { not.setNaikSetengah(); } else if (r.GetAttribute("naikturun").Equals("\\")) { not.setTurunSetengah(); } not.setNilaiNot(Convert.ToSingle(r.GetAttribute("nilai"))); listNotasi.Add(not); } } else if (r.NodeType == XmlNodeType.Text) { Console.WriteLine("\tVALUE: " + r.Value); } } } } } 

对于简单的事情,我只使用System.XML中的XmlDocument / XmlNode / XmlAttribute类和XmlDocument DOM。

它为我生成XML,我只需要将几个项目链接在一起。

但是,在更大的事情上,我使用XML序列化。

对于简单的情况,我也建议看一下XmlOutput构建Xml的流畅接口。

XmlOutput非常适合用可读和可维护的代码进行简单的Xml创建,同时生成有效的Xml。 原帖有一些很好的例子。

如上。

我使用stringbuilder.append()。

非常简单,然后你可以做xmldocument.load(以严格的对象作为参数)。

您可能会发现自己在append参数中使用string.concat,但这是一个非常简单的方法。