Как в цикле считать XML?

есть XML Вида
<?xml version="1.0" encoding="utf-8" ?>
<Backup>
  <Basic>
    <Path1C>\\server\1cv8s.exe</Path1C>
  </Basic>
  <Bases>
    <Base Name="b1" MODE="File" Path="\\server\Base\base"/>
    <Base Name="bas2" MODE="Server" Path="\\server\db"/>
  </Bases>
</Backup>


как его прочитать в цикле?
  • Вопрос задан
  • 301 просмотр
Решения вопроса 1
AlekseyNemiro
@AlekseyNemiro
full-stack developer
1. Использовать XML-сериализацию (все данные будут загружены в память).

Классы
public class Backup
{

  public Basic Basic { get; set; }

  public List<Base> Bases { get; set; }

}

public class Basic
{

  public string Path1C { get; set; }

}

public class Base
{

  [XmlAttribute]
  public string Name { get; set; }

  [XmlAttribute]
  public string Mode { get; set; }

  [XmlAttribute]
  public string Path { get; set; }

}
Пример использования
// из строки
string source =
(
  @"<?xml version=""1.0"" encoding=""utf-8"" ?>
  <Backup>
    <Basic>
      <Path1C>\\server\1cv8s.exe</Path1C>
    </Basic>
    <Bases>
      <Base Name=""b1"" MODE=""File"" Path=""\\server\Base\base""/>
      <Base Name=""bas2"" MODE=""Server"" Path=""\\server\db""/>
    </Bases>
  </Backup>"
);


using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(source)))
{
  var serializer = new XmlSerializer(typeof(Backup));
  var backup = (Backup)serializer.Deserialize(ms);

  foreach (var b in backup.Bases)
  {
    Console.WriteLine("Name: {0}", b.Name);
    Console.WriteLine("MODE: {0}", b.Mode);
    Console.WriteLine("Path: {0}", b.Path);
  }
}

2. Для чтения небольших файлов можно использовать System.Xml.XmlDocument (все данные будут загружены в память):

var xml = new XmlDocument();

// из файла:
// xml.Load("XMLFile1.xml");

// из строки
xml.LoadXml
(
  @"<?xml version=""1.0"" encoding=""utf-8"" ?>
  <Backup>
    <Basic>
      <Path1C>\\server\1cv8s.exe</Path1C>
    </Basic>
    <Bases>
      <Base Name=""b1"" MODE=""File"" Path=""\\server\Base\base""/>
      <Base Name=""bas2"" MODE=""Server"" Path=""\\server\db""/>
    </Bases>
  </Backup>"
);

// читаем и выводим все элементы Base из /Backup/Bases:
foreach (XmlNode n in xml.SelectNodes("/Backup/Bases/Base"))
{
  Console.WriteLine("Name: {0}", n.Attributes["Name"].Value);
  Console.WriteLine("MODE: {0}", n.Attributes["MODE"].Value);
  Console.WriteLine("Path: {0}", n.Attributes["Path"].Value);
}

3. Для больших файлов лучше использовать System.Xml.XmlReader (нагрузка на память минимальная). Для простоты работы, сделать комбинацию из выше указанных методов.

Очень простой, но грубый пример использования XmlReader
string source =
(
  @"<?xml version=""1.0"" encoding=""utf-8"" ?>
  <Backup>
    <Basic>
      <Path1C>\\server\1cv8s.exe</Path1C>
    </Basic>
    <Bases>
      <Base Name=""b1"" MODE=""File"" Path=""\\server\Base\base""/>
      <Base Name=""bas2"" MODE=""Server"" Path=""\\server\db""/>
    </Bases>
  </Backup>"
);

using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(source)))
// если из файла, то без MemoryStream; или лучше использовать FileStream
// using (var xml = XmlReader.Create("XMLFile1.xml"))
using (var xml = XmlReader.Create(ms))
{
  while (xml.Read())
  {
    switch (xml.NodeType)
    {
      case XmlNodeType.Element:
        // нашли элемент Base
        if (xml.Name == "Base")
        {
          // выводим атрибуты
          Console.WriteLine("Name: {0}", xml.GetAttribute("Name"));
          Console.WriteLine("MODE: {0}", xml.GetAttribute("MODE"));
          Console.WriteLine("Path: {0}", xml.GetAttribute("Path"));
        }
        break;
    }
  }
}
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@cicatrix
было бы большой ошибкой думать
public class XmlEntry
{
    public string Name { get; set; }
    public string Mode { get; set; }
    public string Path { get; set; }
} // class XmlEntry

public IEnumerable<XmlEntry> ReadFile(string filename)
{
    XmlDocument doc = new XmlDocument();
    doc.Load(filename);
    return doc.SelectNodes("/Backup/Bases/Base")
        .OfType<XmlElement>()
        .Select(e => new XmlEntry
        {
            Name = e.Attributes["Name"].Value,
            Mode = e.Attributes["MODE"].Value,
            Path = e.Attributes["Path"].Value
        }); // Добавить валидацию, если атрибуты не обязательны
} // ReadFile
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы