如何在C#中构建XML?


Answers:


510

这取决于场景。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;这是更原始的(一次写入型firehose),但是非常有效(在这里想象一个大循环):

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)。


10
不要忘记XStreamingElement,msdn.microsoft.com / en-us / library /… 。:)
托德·怀特

1
对于XmlWriter示例,重要的是要注意,您需要最后关闭writer才能使其正常工作-writer.WriteEndElement()之后需要writer.Close()。
Marko 2015年

@Marko说的是真的:正确关闭编写器很重要。还有另一种方法可以代替直接调用writer.Close()。您可以将对Create()的调用包装在如下using语句中:using(XmlWriter writer = XmlWriter.Create(Console.Out)){writer.WriteStartElement(“ Foo”); }这里还有XmlWriter的另一个(更增强的)示例:dotnetperls.com/xmlwriter
Morten

@Morten确保XmlWriter实现IDisposable,然后using语句是最佳选择。
马可

好的旧XMLDocument拥有了一切。如果要创建XML文档,则简单明了。
FrenkyB

60

我尝试过的最好的方法是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)。


似乎这段代码无法正常工作。当我不想这样做时,没有应用保存功能RootElement
DanilGholtsman 2014年

24
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)
                         )
            );

10

XmlWriter是编写良好XML的最快方法。XDocument,XMLDocument和其他一些工具也可以很好地工作,但是并未针对编写XML进行优化。如果要尽快编写XML,则绝对应该使用XmlWriter。


6
也就是说,如果您希望计算机尽可能快地编写XML。如果您(开发人员)希望以最简单,最自然的方式创建XML,那么XmlWriter可能不是解决方案!
sjy


4

我认为该资源应足以进行适度的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);
            }
    }
}

}
}

1

为了简单起见,我只使用System.XML中的XmlDocument / XmlNode / XmlAttribute类和XmlDocument DOM。

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

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


1

对于简单的情况,我还建议您查看XmlOutput来构建Xml的流畅界面。

XmlOutput非常适合通过可读和可维护的代码简单地创建Xml,同时生成有效的Xml。该原单后有一些很好的例子。


-3

如上。

我使用stringbuilder.append()。

非常简单,然后可以执行xmldocument.load(strinbuilder对象作为参数)。

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


11
除非您忘记正确编码并编写非法的Xml。
罗伯特·保尔森

3
这个答案被完全抨击了,但是基于这个问题,我看了我自己的构建XML的实现之一。对于我的特定项目,我始终发现通过StringBuilder进行构建比使用XDocument / XmlWriter的处理时间快10%。但是,我对XML很满意,这是针对我的特定项目的。(作为参考,最终XML大小约为3.4 MB,超过8000行。)
James Skemp 2010年

2
如果测得的权衡应用程序的性能(?,我们谈论毫秒改善这里)和应用程序的维护之间我很好奇,想知道(做你的工程师需要现在进行更改前一小时的熟悉代码?)
丹Esparza
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.