Làm cách nào tôi có thể xây dựng XML bằng C #?


438

Làm cách nào tôi có thể tạo XML hợp lệ trong C #?

Câu trả lời:


510

Nó phụ thuộc vào kịch bản. XmlSerializerchắc chắn là một cách và có lợi thế là ánh xạ trực tiếp vào mô hình đối tượng. Trong .NET 3.5, XDocumentv.v ... cũng rất thân thiện. Nếu kích thước rất lớn, thìXmlWriter là bạn của bạn.

XDocumentdụ:

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

Hoặc tương tự với 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);

Nếu bạn đang viết một lượng lớn dòng dữ liệu, sau đó bất kỳ của DOM phương pháp tiếp cận (ví dụ như XmlDocument/ XDocument, vv) sẽ nhanh chóng mất rất nhiều bộ nhớ. Vì vậy, nếu bạn đang viết tệp XML 100 MB từ CSV , bạn có thể xem xét XmlWriter; cái này còn nguyên thủy hơn (một loại thuốc chữa cháy một lần), nhưng rất hiệu quả (hãy tưởng tượng một vòng lặp lớn ở đây):

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

Cuối cùng, thông qua 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);

Đây là một mô hình đẹp để ánh xạ tới các lớp, v.v.; tuy nhiên, nó có thể là quá mức nếu bạn đang làm một cái gì đó đơn giản (hoặc nếu XML mong muốn không thực sự có mối tương quan trực tiếp với mô hình đối tượng). Một vấn đề khác XmlSerializerlà nó không muốn tuần tự hóa các loại không thay đổi: mọi thứ đều phải có trình thu thập thiết lập công khai (trừ khi bạn tự làm tất cả bằng cách thực hiện IXmlSerializable, trong trường hợp bạn chưa đạt được nhiều bằng cách sử dụng XmlSerializer).


10
Đừng quên XStreamingEuity, msdn.microsoft.com/en-us/l Library / . :)
Todd White

1
Đối với ví dụ XmlWriter, điều quan trọng cần lưu ý là bạn cần đóng trình ghi ở cuối để nó hoạt động chính xác - wr.Close () là cần thiết sau khi người viết.WriteEndEuity ().
Marko

Đúng như những gì @Marko nói: Điều quan trọng là phải đóng nhà văn đúng cách. Ngoài ra còn có một cách khác để làm điều đó, thay vì gọi trực tiếp cho nhà văn. Đóng () trực tiếp. Bạn có thể gói cuộc gọi để Tạo () trong một câu lệnh sử dụng như thế này: bằng cách sử dụng (XmlWriter wr = XmlWriter.Create (Console.Out)) {wr.WriteStartEuity ("Foo"); vv} Có một ví dụ khác (được nâng cao hơn một chút) về XmlWriter tại đây: dotnetperls.com/xmlwriter
Morten

@Morten Chắc chắn nếu XmlWriter thực hiện IDis Dùng thì sử dụng câu lệnh là lựa chọn tốt nhất.
Marko

XMLDocument cũ tốt có tất cả. Thẳng thắn, đơn giản và rõ ràng nếu bạn đang tạo tài liệu XML.
FrenkyB

60

Điều tốt nhất mà tôi đã thử là LINQ to XSD (điều mà hầu hết các nhà phát triển chưa biết). Bạn cung cấp cho nó một Lược đồ XSD và nó tạo ra một mô hình đối tượng được gõ hoàn toàn được ánh xạ hoàn hảo (dựa trên LINQ to XML) cho bạn trong nền, điều này thực sự dễ dàng để làm việc - và nó cập nhật và xác thực mô hình đối tượng và XML của bạn trong thời gian thực. Mặc dù vẫn là "Xem trước", tôi không gặp phải bất kỳ lỗi nào với nó.

Nếu bạn có Lược đồ XSD trông như thế này:

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

Sau đó, bạn có thể chỉ cần xây dựng XML như thế này:

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

Hoặc đơn giản là tải một XML từ tệp như thế này:

RootElement rootElement = RootElement.Load(filePath);

Hoặc lưu nó như thế này:

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

rootElement.Untyped cũng mang lại thành phần dưới dạng XE đắp (từ LINQ sang XML).


Có vẻ như mã này không hoạt động. Khi tôi muốn làm như thế này, không có fucntion nào được áp dụng choRootElement
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)
                         )
            );

10

XmlWriter là cách nhanh nhất để viết XML tốt. XDocument, XMLDocument và một số thứ khác hoạt động tốt, nhưng không được tối ưu hóa để viết XML. Nếu bạn muốn viết XML càng nhanh càng tốt, bạn chắc chắn nên sử dụng XmlWriter.


6
Đó là, nếu bạn muốn máy tính viết XML càng nhanh càng tốt. Nếu bạn, nhà phát triển, muốn tạo XML theo cách dễ dàng và tự nhiên nhất, XmlWriter có lẽ không phải là giải pháp!
sjy


4

Tôi nghĩ tài nguyên này đủ cho việc lưu / tải XML vừa phải: Đọc / ghi XML bằng C # .

Nhiệm vụ của tôi là lưu trữ ký hiệu âm nhạc. Tôi chọn XML, vì tôi đoán .NET đã trưởng thành đủ để cho phép giải pháp dễ dàng cho nhiệm vụ. Tôi đã đúng :)

Đây là nguyên mẫu tập tin bài hát của tôi:

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

Điều đó có thể được giải quyết khá dễ dàng:

Để lưu vào tệp:

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

 }

Đối với tệp tải:

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

Đối với những điều đơn giản, tôi chỉ sử dụng các lớp XmlDocument / XmlNode / XmlAttribution và XmlDocument DOM được tìm thấy trong System.XML.

Nó tạo ra XML cho tôi, tôi chỉ cần liên kết một vài mục với nhau.

Tuy nhiên, trên những thứ lớn hơn, tôi sử dụng tuần tự hóa XML.


1

Đối với các trường hợp đơn giản, tôi cũng đề nghị xem xét XmlOutput một giao diện lưu loát để xây dựng Xml.

XmlOutput rất tốt cho việc tạo Xml đơn giản với mã có thể đọc và duy trì được, trong khi tạo Xml hợp lệ. Bài viết ban đầu có một số ví dụ tuyệt vời.


-3

Như trên.

Tôi sử dụng Stringbuilder.append ().

Rất đơn giản, và sau đó bạn có thể thực hiện xmldocument.load (đối tượng strinbuilder làm tham số).

Bạn có thể sẽ thấy mình sử dụng string.concat trong tham số chắp thêm, nhưng đây là một cách tiếp cận rất đơn giản.


11
Ngoại trừ khi bạn quên mã hóa một cái gì đó đúng cách và viết Xml bất hợp pháp.
Robert Paulson

3
Câu trả lời này hoàn toàn bị đánh sập, nhưng dựa trên câu hỏi này, tôi đã xem xét một trong những triển khai của riêng tôi nơi tôi xây dựng XML. Đối với dự án cụ thể của tôi, tôi luôn thấy rằng việc xây dựng thông qua StringBuilder dẫn đến thời gian xử lý nhanh hơn 10% so với sử dụng XDocument / XmlWriter. Nhưng, tôi cảm thấy thoải mái với XML và đó là dự án cụ thể của tôi. (Để tham khảo, kích thước XML cuối cùng là khoảng 3,4 MB, với hơn 8000 dòng.)
James Skemp

2
Tôi tò mò muốn biết liệu bạn đã đo lường sự đánh đổi giữa hiệu suất ứng dụng (chúng ta đang nói về cải tiến mili giây ở đây phải không?) Và bảo trì ứng dụng (các kỹ sư của bạn có cần làm quen với mã trong một giờ trước khi thực hiện thay đổi không?)
Dan Esparza
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.