Bagaimana saya bisa membangun XML dalam C #?

438

Bagaimana saya bisa menghasilkan XML yang valid dalam C #?

Dan Esparza
sumber

Jawaban:

510

Itu tergantung skenario. XmlSerializertentu saja merupakan salah satu cara dan memiliki keuntungan pemetaan langsung ke model objek. Dalam. NET 3.5 XDocument,, dll. Juga sangat ramah. Jika ukurannya sangat besar, maka XmlWriterteman Anda.

Sebagai XDocumentcontoh:

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

Atau sama dengan 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);

Jika Anda menulis besar aliran data, maka setiap dari DOM pendekatan (seperti XmlDocument/ XDocument, dll) dengan cepat akan mengambil banyak memori. Jadi jika Anda menulis file XML 100 MB dari CSV , Anda dapat mempertimbangkan XmlWriter; ini lebih primitif (firehose tulis-sekali), tetapi sangat efisien (bayangkan loop besar di sini):

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

Akhirnya, melalui 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);

Ini adalah model yang bagus untuk pemetaan ke kelas, dll .; Namun, itu mungkin berlebihan jika Anda melakukan sesuatu yang sederhana (atau jika XML yang diinginkan tidak benar-benar memiliki korelasi langsung dengan model objek). Masalah lainnya XmlSerializeradalah bahwa ia tidak suka membuat serial jenis-jenis yang tidak dapat diubah: semuanya harus memiliki pengambil dan penyetel publik (kecuali jika Anda melakukan semuanya sendiri dengan menerapkan IXmlSerializable, dalam hal ini Anda belum mendapatkan banyak dengan menggunakan XmlSerializer).

Marc Gravell
sumber
10
Jangan lupa tentang XStreamingElement, msdn.microsoft.com/en-us/library/… . :)
Todd White
1
Sebagai contoh XmlWriter, penting untuk dicatat bahwa Anda harus menutup penulis di akhir agar berfungsi dengan baik - penulis. Tutup () diperlukan setelah penulis. MenulisEndElement ().
Marko
Memang benar apa yang dikatakan @Marko: Penting untuk menutup penulis dengan benar. Ada juga cara lain untuk melakukan itu, sebagai pengganti memanggil penulis. Tutup () secara langsung. Anda dapat membungkus panggilan ke Buat () dalam pernyataan menggunakan seperti ini: using (XmlWriter writer = XmlWriter.Create (Console.Out)) {writer.WriteStartElement ("Foo"); dll} Ada contoh XmlWriter (sedikit lebih ditingkatkan) di sini: dotnetperls.com/xmlwriter
Morten
@Morten Yakin jika XmlWriter mengimplementasikan IDisposable maka menggunakan pernyataan adalah pilihan terbaik.
Marko
XMLDocument tua yang baik memiliki semuanya. Lurus, sederhana dan jelas jika Anda membuat dokumen XML.
FrenkyB
60

Hal terbaik yang saya coba adalah LINQ to XSD (yang tidak diketahui oleh kebanyakan pengembang). Anda memberikan Skema XSD dan menghasilkan model objek yang sangat diketik lengkap yang dipetakan dengan sempurna (berdasarkan LINQ ke XML) untuk Anda di latar belakang, yang sangat mudah untuk dikerjakan - dan ini memperbarui serta memvalidasi model objek dan XML Anda di waktu sebenarnya. Meskipun masih "Pratinjau", saya belum menemukan bug apa pun dengannya.

Jika Anda memiliki Skema XSD yang terlihat seperti ini:

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

Maka Anda cukup membangun XML seperti ini:

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

Atau cukup memuat XML dari file seperti ini:

RootElement rootElement = RootElement.Load(filePath);

Atau simpan seperti ini:

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

rootElement.Untyped juga menghasilkan elemen dalam bentuk XElement (dari LINQ ke XML).

pengguna65199
sumber
Sepertinya kode ini bukan kode yang berfungsi. ketika saya rty untuk membuat seperti ini tidak ada fucntion Simpan diterapkan keRootElement
DanilGholtsman
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)
                         )
            );
Vincent
sumber
10

XmlWriter adalah cara tercepat untuk menulis XML yang bagus. XDocument, XMLDocument dan beberapa yang lainnya juga berfungsi dengan baik, tetapi tidak dioptimalkan untuk menulis XML. Jika Anda ingin menulis XML secepat mungkin, Anda harus menggunakan XmlWriter.

Mikael Söderström
sumber
6
Artinya, jika Anda ingin komputer menulis XML secepat mungkin. Jika Anda, pengembang, ingin membuat XML dengan cara termudah dan paling alami, XmlWriter mungkin bukan solusinya!
sjy
4

Saya pikir sumber daya ini cukup untuk XML save / load moderat: Baca / Tulis XML menggunakan C # .

Tugas saya adalah menyimpan notasi musik. Saya memilih XML, karena saya kira . NET telah cukup matang untuk memungkinkan solusi yang mudah untuk tugas tersebut. Saya benar :)

Ini adalah prototipe file lagu saya:

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

Itu bisa diselesaikan dengan mudah:

Untuk Simpan ke File:

 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();
     }

 }

Untuk memuat file:

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

}
}
swdev
sumber
1

Untuk hal-hal sederhana, saya hanya menggunakan kelas XmlDocument / XmlNode / XmlAttribute dan XmlDocument DOM yang ditemukan di System.XML.

Ini menghasilkan XML untuk saya, saya hanya perlu menghubungkan beberapa item bersama.

Namun, pada hal-hal yang lebih besar, saya menggunakan serialisasi XML.

FlySwat
sumber
1

Untuk kasus sederhana, saya juga menyarankan melihat XmlOutput antarmuka yang fasih untuk membangun Xml.

XmlOutput sangat bagus untuk pembuatan Xml sederhana dengan kode yang dapat dibaca dan dikelola, sambil menghasilkan Xml yang valid. The posting asli memiliki beberapa contoh besar.

Todd
sumber
-3

Seperti di atas.

Saya menggunakan stringbuilder.append ().

Sangat mudah, dan Anda kemudian dapat melakukan xmldocument.load (objek strinbuilder sebagai parameter).

Anda mungkin akan menemukan diri Anda menggunakan string.concat dalam parameter append, tetapi ini adalah pendekatan yang sangat mudah.

GurdeepS
sumber
11
Kecuali ketika Anda lupa untuk menyandikan sesuatu dengan benar dan menulis Xml ilegal.
Robert Paulson
3
Jawaban ini benar-benar dibanting, tetapi berdasarkan pertanyaan ini saya melihat salah satu implementasi saya sendiri di mana saya membangun XML. Untuk proyek khusus saya, saya secara konsisten menemukan bahwa membangun melalui StringBuilder menghasilkan waktu pemrosesan 10% lebih cepat daripada menggunakan XDocument / XmlWriter. Tapi, saya merasa nyaman dengan XML, dan itu untuk proyek khusus saya. (Untuk referensi, ukuran XML final sekitar 3,4 MB, dengan lebih dari 8000 baris.)
James Skemp
2
Saya ingin tahu jika Anda mengukur pertukaran antara kinerja aplikasi (apakah kita berbicara perbaikan milidetik di sini?) Dan pemeliharaan aplikasi (apakah teknisi Anda perlu membiasakan diri dengan kode selama satu jam sebelum melakukan perubahan sekarang?)
Dan Esparza