【问题标题】:How can I build XML in C#?如何在 C# 中构建 XML?
【发布时间】:2010-09-22 00:14:20
【问题描述】:

如何在 C# 中生成有效的 XML?

【问题讨论】:

    标签: c# xml


    【解决方案1】:

    这取决于场景。 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 并没有太大收获。

    【讨论】:

    • 别忘了 XStreamingElement,msdn.microsoft.com/en-us/library/…。 :)
    • 对于 XmlWriter 示例,重要的是要注意您需要在最后关闭编写器才能使其正常工作 - 在 writer.WriteEndElement() 之后需要 writer.Close()。
    • @Marko 说的是真的:正确关闭作者很重要。还有另一种方法可以做到这一点,而不是直接调用 writer.Close()。您可以将 Create() 调用包装在这样的 using 语句中: using(XmlWriter writer = XmlWriter.Create(Console.Out)) { writer.WriteStartElement("Foo");等 } 这里还有另一个(更强大的)XmlWriter 示例:dotnetperls.com/xmlwriter
    • @Morten 当然如果 XmlWriter 实现了 IDisposable 那么 using 语句是最好的选择。
    • 好旧的 XMLDocument 拥有一切。如果您正在创建 XML 文档,则直接、简单和清晰。
    【解决方案2】:

    我尝试过的最好的方法是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
    【解决方案3】:
    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)
                             )
                );
    

    【讨论】:

      【解决方案4】:

      XmlWriter 是编写良好 XML 的最快方法。 XDocument、XMLDocument 和其他一些也很好用,但没有针对编写 XML 进行优化。如果你想尽可能快地编写 XML,你绝对应该使用 XmlWriter。

      【讨论】:

      • 也就是说,如果您希望 计算机 尽可能快地写入 XML。如果您作为开发人员,想以最简单、最自然的方式创建 XML,那么 XmlWriter 可能不是解决方案!
      【解决方案5】:

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

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

      【讨论】:

        【解决方案6】:

        我认为这个资源应该足以进行适度的 XML 保存/加载:Read/Write XML using C#

        我的任务是存储乐谱。我选择 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);
                    }
            }
        }
        
        }
        }
        

        【讨论】:

          【解决方案7】:

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

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

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

          【讨论】:

            【解决方案8】:

            对于简单的情况,我还建议查看XmlOutput 一个用于构建 Xml 的流畅接口。

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

            【讨论】:

              【解决方案9】:

              如上。

              我使用 stringbuilder.append()。

              很简单,然后就可以做xmldocument.load(strinbuilder object as parameter)了。

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

              【讨论】:

              • 除非您忘记正确编码某些内容并编写非法Xml。
              • 这个答案得到了绝对的抨击,但基于这个问题,我看了一下我自己构建 XML 的实现之一。对于我的特定项目,我始终发现通过 StringBuilder 构建比使用 XDocument/XmlWriter 的处理时间快 10%。但是,我对 XML 感觉很舒服,这是针对我的特定项目的。 (作为参考,最终的 XML 大小约为 3.4 MB,超过 8000 行。)
              • 我很想知道您是否衡量了应用程序性能(我们在这里谈论的是毫秒级改进吗?)和应用程序维护(您的工程师是否需要花一个小时熟悉代码)之间的权衡现在进行更改之前?)
              猜你喜欢
              • 1970-01-01
              • 2010-12-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-03-12
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多