Как я могу построить XML в C #?

438

Как я могу создать действительный XML в C #?

Dan Esparza
источник

Ответы:

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 важно отметить, что вам нужно закрыть писатель в конце, чтобы он работал правильно - writer.Close () необходим после writer.WriteEndElement ().
Марко
Это правда, что @Marko говорит: важно правильно закрыть писателя. Существует также другой способ сделать это, вместо непосредственного вызова writer.Close (). Вы можете обернуть вызов Create () в оператор using следующим образом: using (XmlWriter writer = XmlWriter.Create (Console.Out)) {writer.WriteStartElement ("Foo"); и т. д.} Здесь есть еще один (немного более улучшенный) пример XmlWriter: dotnetperls.com/xmlwriter
Мортен,
@Morten Конечно, если XmlWriter реализует IDisposable, тогда использование оператора - лучший вариант.
Марко
У старого доброго XMLDocument есть все. Прямо, просто и понятно, если вы создаете документ XML.
FrenkyB
60

Лучшее, что я попробовал, это LINQ to XSD (что неизвестно большинству разработчиков). Вы даете ему схему XSD, и она генерирует идеально отображенную полную объектную модель со строгой типизацией (на основе 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).

user65199
источник
Кажется, что этот код не работает код. когда я хочу сделать это, функция сохранения не применяется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)
                         )
            );
Vincent
источник
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);
            }
    }
}

}
}
swdev
источник
1

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

Он генерирует XML для меня, мне просто нужно связать несколько элементов вместе.

Однако на более крупных вещах я использую сериализацию XML.

FlySwat
источник
1

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

XmlOutput отлично подходит для простого создания Xml с читаемым и поддерживаемым кодом, в то же время генерируя действительный Xml. Оригинал пост имеет много примеров.

Тодд
источник
-3

Как указано выше.

Я использую stringbuilder.append ().

Очень просто, и вы можете сделать xmldocument.load (объект strinbuilder в качестве параметра).

Вероятно, вы обнаружите, что используете string.concat в параметре append, но это очень простой подход.

GurdeepS
источник
11
За исключением случаев, когда вы забыли правильно что-то кодировать и написали нелегальный Xml.
Роберт Полсон
3
Этот ответ был абсолютно решен, но на основе этого вопроса я взглянул на одну из моих собственных реализаций, где я строю XML. Для моего конкретного проекта я постоянно обнаруживал, что сборка через StringBuilder приводит к увеличению времени обработки на 10% по сравнению с использованием XDocument / XmlWriter. Но я чувствую себя комфортно с XML, и это для моего конкретного проекта. (Для справки, окончательный размер XML составляет около 3,4 МБ, с более чем 8000 строк.)
Джеймс Скемп
2
Мне было бы любопытно узнать, измеряли ли вы компромисс между производительностью приложений (мы говорим об улучшениях в миллисекундах?) И обслуживанием приложений (должны ли ваши инженеры ознакомиться с кодом в течение часа, прежде чем вносить изменения сейчас?)
Дэн Esparza