С# Добавление данных в xml-файл

Я создаю приложение Parts, чтобы изучить C# и WPF. У меня возникли проблемы с добавлением новых частей с помощью XmlWriter. Я могу создать файл xml, но не могу понять, как добавить дополнительные части. Должен ли я использовать что-то еще, например XmlDocument? Вот мой код:

private void btnSave_Click(object sender, RoutedEventArgs e)
    {

        XmlWriterSettings settings = new XmlWriterSettings();
        settings.Encoding = Encoding.UTF8;
        settings.Indent = true;

        using (XmlWriter writer = XmlWriter.Create("f:\\MyParts.xml", settings))
        {
            writer.WriteStartDocument();
            writer.WriteStartElement("MyParts");
            writer.WriteStartElement("parts");
            writer.WriteStartElement("item");
            writer.WriteString(txtbxitem.Text);
            writer.WriteEndElement();

            writer.WriteStartElement("color");
            writer.WriteString(txtbxcolor.Text);
            writer.WriteEndElement();

            writer.WriteStartElement("size");
            writer.WriteString(txtbxsize.Text);
            writer.WriteEndElement();

            writer.WriteEndElement();
            writer.WriteEndDocument();

            writer.Flush();
            writer.Close();

        }
    }

Этот код правильно создает файл xml и узел, но как добавить дополнительные части? Вот что я пытаюсь создать:

 <?xml version="1.0" encoding="ISO-8859-1" ?> 

<MyParts>
  <parts>
    <item>Part1</item>
    <color>Red</color>
    <size>SM</size>
  </parts>
  <parts>
    <item>Part2</item>
    <color>Blue</color>
    <size>XXL</size>
  </parts>
</MyParts>

person Lone Starr    schedule 06.10.2010    source источник


Ответы (4)


Лично я бы предложил использовать LINQ to XML. Это намного более простой в использовании API, чем XmlDocument.

Но да, если вы хотите изменить существующий документ, обычно использование представления в памяти проще, чем использование потокового API. Конечно, возможно сделать последнее, но это непросто.

Вот пример создания того же XML, который у вас уже есть (кроме объявления: любая причина, по которой вы хотите использовать Latin-1 вместо чего-то вроде UTF-8, который может представлять весь Юникода, кстати?)

var doc = new XDocument(
  new XElement("MyParts",
    new XElement("parts",
      new XElement("item", "Part1"),
      new XElement("color", "Red"),
      new XElement("size", "SM")),
    new XElement("parts",
      new XElement("item", "Part2"),
      new XElement("color", "Blue"),
      new XElement("size", "XXL"))));

Затем, если вы хотите добавить еще одну часть:

doc.Root.Add(
  new XElement("parts",
    new XElement("item", "Part3"),
    new XElement("color", "Green"),
    new XElement("size", "L")));

По общему признанию, я ожидаю, что вы захотите инкапсулировать бит «создать элемент частей» в метод, чтобы избежать его повторения все время... но, надеюсь, вы поняли картину.

person Jon Skeet    schedule 06.10.2010
comment
Считаете ли вы, что LINQ to XML — лучший способ создания и редактирования XML-файлов с помощью С#? Я хочу тратить время на обучение с умом. - person Lone Starr; 06.10.2010
comment
@Lone: Если вы можете использовать .NET 3.5 или выше, это лучшее решение для большинства проблем. Если вы имеете дело с огромным файлом, XmlReader может оказаться полезным, но я бы по крайней мере начал с LINQ to XML. - person Jon Skeet; 06.10.2010
comment
Я согласен с @Jon: чем проще, тем лучше! Здесь я имею дело с простым документом Xml, и XDocument довольно хорош и прост в создании моего контента (что вы видите, то и получаете). - person Junior Mayhé; 11.10.2010

Используйте цикл, и вы получите что-то вроде:

    var parts = new List<Part>() { ...... parts here ...... };        

    using (XmlWriter writer = XmlWriter.Create("f:\\MyParts.xml", settings))
    {
        writer.WriteStartDocument();
        writer.WriteStartElement("MyParts");

        foreach(var part in parts)
        {
            writer.WriteStartElement("parts");
            writer.WriteStartElement("item");
            writer.WriteString(part.Item);
            writer.WriteEndElement(); // </item>

            writer.WriteStartElement("color");
            writer.WriteString(part.Color);
            writer.WriteEndElement();

            writer.WriteStartElement("size");
            writer.WriteString(part.Size);
            writer.WriteEndElement(); // </size>

            writer.WriteEndElement(); // </parts>
        }
        writer.WriteEndElement(); // </MyParts>
        writer.WriteEndDocument();

        writer.Flush();
        writer.Close();

    }

Общая идея состоит в том, что для каждой части в вашем списке частей вы пишете тег «части» (должно быть «часть»?) и все его содержимое, заполняя item, color и size данными из класса Part, который в простейшем виде может быть:

class Part
{
    public string Item { get; set; }
    public Color Color { get; set; }
    public string Size { get; set; }
}
person Martin Törnwall    schedule 06.10.2010

Приведенный выше код делает именно то, на что он похож: записывает элемент «MyParts», затем записывает дочерний элемент «parts», а затем дочерний элемент «item» со значением того, что находится в вашем текстовом поле.

Это подозрительно пахнет домашним заданием, и его легко найти в Google, поэтому я дам лишь быстрый псевдо-ответ.

Вы (можете) хотите:

  1. Создайте соответствующий класс (ы) для частей, которые имеют нужные вам элементы.
  2. Создайте коллекцию этих элементов
  3. Обновите эту коллекцию в памяти из вашего пользовательского интерфейса.
  4. Сохраните коллекцию, используя форматирование XML и функциональные возможности по вашему выбору (включая, помимо прочего, то, что вы делаете выше, или LINQ to XML, или сериализацию XML, или...)
person Wonko the Sane    schedule 06.10.2010
comment
Я думал, что редактировать файл xml будет легко. Я гуглил в течение нескольких дней, что, вероятно, лучше всего описывает мой уровень навыков. Я даже не знал, с чего начать, но в конце концов добрался до xmlwriter, который работал (как вы знаете), но затем мне указали на XmlDocument. Все, что я пробовал, всегда перезаписывает, но не добавляет. Я видел LINQ to XML во время поиска, так что знайте, что я буду искать его. Я также проверю сериализацию XML. - person Lone Starr; 06.10.2010

Рассматривали ли вы возможность использования встроенной XML-сериализации, поставляемой с .NET? Вы просто заполняете свои объекты в некоторой коллекции, а затем используете сериализатор XML для сохранения в файле. Затем вы можете использовать DeSerializer для гидратации ваших объектов.

Это позволит вам тратить больше времени на пользовательский интерфейс вашего приложения (WPF) и логику. Все, что вам нужно сделать, это все атрибуты Serializable для вашего класса.

Вот хороший пример: http://www.jonasjohn.de/snippets/csharp/xmlserializer-example.htm

Самое большое преимущество заключается в том, что по мере того, как вы создаете свой объект данных с течением времени, сериализация/десериализация будет расти вместе с ним.

person Babak Naffas    schedule 06.10.2010