Як я можу побудувати XML у C #?


Відповіді:


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тощо) швидко забирає багато пам'яті. Отже, якщо ви пишете XML-файл розміром 100 Мб з CSV , можете подумати XmlWriter; це більш примітивне (колись записування), але дуже ефективне (уявіть собі велику петлю тут):

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полягає в тому, що він не любить серіалізувати непорушні типи: все повинно мати публічний геттер і сетер (якщо тільки ви все це не зробите самостійно, реалізуючи IXmlSerializable, і в цьому випадку ви багато не заробили, використовуючи XmlSerializer).


10
Не забувайте про XStreamingElement, msdn.microsoft.com/en-us/library/… . :)
Тодд Уайт

1
Для прикладу XmlWriter важливо зауважити, що вам потрібно закрити автору в кінці, щоб він працював належним чином - write.Close () потрібен після Writer.WriteEndElement ().
Марко

Це правда, що говорить @Marko: Важливо правильно закрити письменника. Існує також інший спосіб зробити це, замість того, щоб зателефонувати автору. Закрийте () безпосередньо. Ви можете зафіксувати виклик Create () у використовуваному операторі на зразок цього: використовуючи (XmlWriter Writer = XmlWriter.Create (Console.Out)) {Writ.WriteStartElement ("Foo"); і т.д.} Тут є ще один (трохи більш розширений) приклад XmlWriter: dotnetperls.com/xmlwriter
Morten

@Morten Звичайно, якщо XmlWriter реалізує IDisposable, тоді найкращим варіантом є використання оператора.
Марко

Добрий старий XMLDocument має все це. Прямий, простий і зрозумілий, якщо ви створюєте XML-документ.
FrenkyB

60

Найкраще, що я спробував, це LINQ до XSD (що невідомо більшості розробників). Ви надаєте йому схему XSD, і вона створює ідеально відображену повну сильно типізовану модель об'єкта (на основі LINQ до 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).


видається, що цей код не працює. коли я rty зробити так, немає ніяких збережених фукцій, застосованих доRootElement
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 - це найшвидший спосіб написання хорошого XML. XDocument, XMLDocument та деякі інші працюють добре, але не оптимізовані для написання XML. Якщо ви хочете написати XML якомога швидше, вам обов'язково слід використовувати XmlWriter.


6
Тобто, якщо ви хочете, щоб комп'ютер записував XML якомога швидше. Якщо ви, розробник, хочете створити XML найпростішим і природнішим способом, XmlWriter, мабуть, не є рішенням!
sjy

4

Раніше я створював свою XML-схему, потім використовував інструмент для генерації класів C #, який буде серіалізуватись до цієї схеми. Інструмент визначення схеми XML - один із прикладів

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


4

Я думаю, цього ресурсу повинно вистачити для помірного збереження / завантаження XML: Читання / запис XML за допомогою 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);
            }
    }
}

}
}

1

Для простих речей я просто використовую класи XmlDocument / XmlNode / XmlAttribute та XMLDocument DOM, знайдені в System.XML.

Він генерує XML для мене, мені просто потрібно зв’язати кілька елементів разом.

Однак у великих речах я використовую XML-серіалізацію.


1

Для простих випадків я б також запропонував подивитися на XmlOutput вільний інтерфейс для створення Xml.

XmlOutput чудово підходить для простого створення Xml з читабельним та підтримуваним кодом, створюючи при цьому дійсні Xml. Оригінал пост має багато прикладів.


-3

Як зазначено вище.

Я використовую stringbuilder.append ().

Дуже просто, і тоді ви можете зробити xmldocument.load (об’єкт strinbuilder як параметр).

Ви, ймовірно, опинитесь за допомогою string.concat в параметрі додавання, але це дуже простий підхід.


11
За винятком випадків, коли ви забудете кодувати щось належним чином і написати незаконний Xml.
Роберт Полсон,

3
Ця відповідь отримала абсолютно глухий вигляд, але грунтуючись на цьому питанні, я переглянув одну із моїх власних реалізацій, де я будую XML. У моєму конкретному проекті я послідовно виявляв, що побудова за допомогою StringBuilder призводить до обробки разів на 10% швидше, ніж використання XDocument / XmlWriter. Але я відчуваю себе комфортно з XML, і це для мого конкретного проекту. (Для довідки, кінцеві розміри XML становлять близько 3,4 Мб, понад 8000 рядків.)
Джеймс Скемп

2
Мені буде цікаво дізнатись, чи ви оцінювали компроміс між продуктивністю програми (ми тут говоримо про поліпшення мілісекунд?) Та технічним обслуговуванням додатків (чи ваші інженери повинні ознайомитися з кодом за годину, перш ніж зараз вносити зміни?)
Ден Еспарза
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.