Работа с XML


9 0

Сегодня я продолжаю разговор о трех нововведениях, которые мне понравились в VS 2008. Не смотря на то, что я пока не рекомендую использовать Linq к базам (не запрещаю, а просто не могу рекомендовать, пока сам не увидел реальную выгоду), для доступа к XML эту выгоду я уже увидел и однозначно рекомендую к использованию.

Допустим, что у нас есть XML файлик со следующим содержимым

<?xml version="1.0"?>
<peoples Version="1">
  <Persen name="Smirnov" city="Vologda" phone="01" />
  <Persen name="Flenov" city="Moscow" phone="02" />
  <Persen name="Ivanov" city="Piter" phone="03" />
  <Persen name="Petrov" city="Moscow" phone="04" />
  <Persen name="Sodorov" city="Moscow" phone="05" />
  <Persen name="Leonov" city="Rostov" phone="06" />
  <Persen name="Ketei" city="Piter" phone="07" />
</peoples>

Как нам загрузить из него данные? С помощью Linq эта задача решается легко и не принужденно. Способ 1 - загрузить XML файл и выполнить к нему запрос:

static IEnumerable GetPeoples()
{
  return from c in XDocument.Load("peoples.xml").
             Descendants("peoples").Descendants()
  select new Person 
  {
   UserName = (string)c.Attribute("name"),
   City = (string)c.Attribute("city"),
   Phone = (string)c.Attribute("phone")
  };
}

Во время загрузки создается массив из классов Person. Этот класс я уже описывал в предыдущей статье 3 возможности, которые мне понравились

Метод GetPeoples() написанный выше возвращает все строки. Чтобы выбрать только москву, можно выполнить следующий код:

var results = from c in GetPeoples()
where c.City == "Moscow"
select c;

Еще один вараинт запроса:

Console.WriteLine("Query result for Piter");
XDocument doc = XDocument.Load("peoples.xml");

var r = from c in doc.Descendants("peoples").Descendants()
where (string)c.Attribute("city") == "Piter"
select c;

Этот вариант проще, потому что не нужно использовать вспомогательный класс Person. Обработка идет сразу же над данными XML файла.

А теперь допустим, что нам нужно выбрать всех, кто живет в Питере и сохранить их в отдельный файл. С помощью Linq эта задача решается очень даже красиво:

 XElement outXML = new XElement("PeoplesFromPiter",
  from person in r
   select new XElement("Person",
     new XAttribute("name", (string)person.Attribute("name")),
     new XElement("city", (string)person.Attribute("city")),
     new XElement("phone", (string)person.Attribute("phone"))
    ));
   outXML.Save("out.xml");

Прекрасно? Я думаю да. Полный код, объединяющий все эти примеры:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace XMLLinq
{
 public class Person
 {
  public string UserName { get; set; }
  public string City { get; set; }
  public string Phone { get; set; }

  public override string ToString()
  {
   return UserName + "\t" + City + "\t" + Phone;
  }
 }

 class Program
 {
  // загрузка в массив XML данных
  static IEnumerable GetPeoples()
  {
   return from c in XDocument.Load("peoples.xml").
             Descendants("peoples").Descendants()
   select new Person 
   {
    UserName = (string)c.Attribute("name"),
    City = (string)c.Attribute("city"),
    Phone = (string)c.Attribute("phone")
   };
  }

 static void Main(string[] args)
 {
  // Выполнение запроса к загруженным
  // с помощью GetPeoples данным
  Console.WriteLine("Query result Moscow");
  var results = from c in GetPeoples()
     where c.City == "Moscow"
     select c;

  foreach (var c in results)
    Console.WriteLine(c);

  // обращение непосредственно к данным
  // без промежуточного массива
  Console.WriteLine("Query result for Piter");
  XDocument doc = XDocument.Load("peoples.xml");

  var r = from c in doc.Descendants("peoples").Descendants()
     where (string)c.Attribute("city") == "Piter"
     select c;

  foreach (var c in r)
    Console.WriteLine(c);

  // Выбираем всех питерцев и сохраняем в отдельный файл
  XElement outXML = new XElement("PeoplesFromPiter",
     from person in r
     select new XElement("Person",
       new XAttribute("name", (string)person.Attribute("name")),
       new XElement("city", (string)person.Attribute("city")),
       new XElement("phone", (string)person.Attribute("phone"))
      ));
   outXML.Save("out.xml");

   Console.ReadLine();
  }
 }
}

Понравилось? Кликни Лайк, чтобы я знал, какой контент более интересен читателям. Заметку пока еще никто не лайкал и ты можешь быть первым


Комментарии

pena

25 Aпреля 2008

Спасибо за статью


GN

25 Aпреля 2008

Михаил, ответьте пожалуйста на такой вопрос:
Далее на блоге в основном будут статьи о майкрософт и её продукции?


f.e.nix

25 Aпреля 2008

просто и красиво: 2 вещи, которые я не нашел в С++ и за которые мне нравится с#


Михаил Фленов

25 Aпреля 2008

2GN: Блог будет о том, что меня больше интересует в данный момент. На данный момент я больше программирую на C#, но не факт, что завтра буду писать здесь о Visual Basic или Java. Хотя нет, завтра об этом точно писать не буду, потому что C# похоже влез в мою голову на долго.


Lobzik_

25 Aпреля 2008

1. Да, технологии клиент-сервер просто &quot;нечего делать&quot; после появления связки XML-Linq. Полный фетч на клиента, а затем только уменьшение выборки (задание условая) полный бред, при выборке даже средних размеров;

2. Согласно DOM (Documentum Object Model) по умолчанию ВЕСЬ XML файл грузится целиком в оперативную память, а только затем данные доступны для обработки через методы класса XDocument. Были у нас &quot;умельцы&quot; которые присылали нам справочник банков в формате XML
~ 900MB, так пока не заставили присылать справочник частями, серваку было &quot;плохо&quot; при загрузке справочника со всеми вытекающими последствиями.

З.Ы. Данная технология может использоваться только для маленьких наборов данных, например хранении и считывании настроек приложения.


Михаил Фленов

25 Aпреля 2008

&gt; Данная технология может использоваться только для маленьких наборов данных

А кто-то использует XML как базу данных?


plaha

27 Aпреля 2008

Спасибо я тоже начал VS мучать


sn1per

27 Aпреля 2008

&gt; А кто-то использует XML как базу данных?

Мы используем MS SQL. В таблицу вписываем XML файл с данными


ast

07 Мая 2008

насколько я помню linq поддерживает в данный момент только ms sql...


Добавить Комментарий

Еще что-нибудь

Хотите найти еще что-то интересное почитать? Можно попробовать отфильтровать заметки на блоге по категориям.

О блоге

Программист, автор нескольких книг серии глазами хакера и просто блогер. Интересуюсь безопасностью, хотя хакером себя не считаю

Обратная связь

Без проблем вступаю в неразборчивые разговоры по e-mail. Стараюсь отвечать на письма всех читателей вне зависимости от страны проживания, вероисповедания, на русском или английском языке.

Пишите мне