如何在C#中构建XML?

How can I build XML in C#?

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


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

对于XDocument示例:

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

或与XmlDocument相同:

1
2
3
4
5
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),但非常有效(假设这里有一个大循环):

2

最后,通过XmlSerializer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[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模式,它会在后台为你生成一个完全映射的、完整的、强类型的对象模型(基于linq-to-xml),这非常容易使用——它会实时更新和验证你的对象模型和XML。虽然它仍然是"预览",但我没有遇到任何错误。

如果您的XSD架构如下所示:

1
2
3
4
5
6
7
8
9
10
  <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:

1
2
3
4
5
RootElement rootElement = new RootElement;
rootElement.Element1 ="Element1";
rootElement.Element2 ="Element2";
rootElement.Attribute1 = 5;
rootElement.Attribute2 = true;

或者简单地从如下文件加载XML:

1
RootElement rootElement = RootElement.Load(filePath);

或者像这样保存:

1
2
3
rootElement.Save(string);
rootElement.Save(textWriter);
rootElement.Save(xmlWriter);

rootElement.Untyped还生成Xelement形式的元素(从linq到xml)。


1
2
3
4
5
6
7
8
9
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(read:linq-to-xml)一次尝试。它简单、直观、易于编辑。

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


还可以查看MarkS.Rasmussen的XMLDocumentFluent接口,它真正提供了易于输入/读取的XML输出。


XML编写器是编写好XML的最快方法。xdocument、xmldocument和其他一些方法也可以很好地工作,但没有针对编写XML进行优化。如果您希望尽可能快地编写XML,那么一定要使用XML编写器。


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

我的任务是存储音乐符号。我选择XML,因为我想.NET已经足够成熟,可以为任务提供简单的解决方案。我是对的:

这是我的歌曲文件原型:

1
2
3
4
5
6
7
<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>

这很容易解决:

保存到文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 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();
     }

 }

加载文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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);
            }
    }
}

}
}

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

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


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

在生成有效的XML时,xmlOutput非常适合使用可读和可维护的代码创建简单的XML。《原始邮报》有一些很好的例子。


对于简单的事情,我只使用在system.xml中找到的xmldocument/xmlnode/xmltattribute类和xmldocument dom。

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

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


如上所述。

我使用StringBuilder.append()。

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

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