З.П.И. » Страница ' Работаем с LINQ to XML'

Работаем с LINQ to XML

В первой статье в блоге .NET «Работаем с XML» в комментариях народ потребовал статьи LINQ to XML. Что же, попробуем раскрыть принципы работы этой новой технологии от Microsoft.

Создадим базу для ведения каталога аудиозаписей. База будет состоять из треков:

* Код
* Название
* Исполнитель
* Альбом
* Продолжительность
* Жанр

Мы научимся добавлять, редактировать, удалять и делать различные выборки из нашей базы.

Для начала создадим консольное приложение (я пишу свои проекты на C#, но суть в общем-то понятна будет всем) и подключим необходимое пространство имен

using System.Xml.Linq;

Создание файлов XML
Создадим XML файл нашей базы содержащий несколько тестовых записей уже при помощи LINQ:

//задаем путь к нашему рабочему файлу XML
string fileName = “base.xml”;

//счетчик для номера композиции
int trackId = 1;
//Создание вложенными конструкторами.
XDocument doc = new XDocument(
new XElement(“library”,
new XElement(“track”,
new XAttribute(“id”, trackId++),
new XAttribute(“genre”, “Rap”),
new XAttribute(“time”, “3:24″),
new XElement(“name”, “Who We Be RMX (feat. 2Pac)”),
new XElement(“artist”, “DMX”),
new XElement(“album”, “The Dogz Mixtape: Who’s Next?!”)),
new XElement(“track”,
new XAttribute(“id”, trackId++),
new XAttribute(“genre”, “Rap”),
new XAttribute(“time”, “5:06″),
new XElement(“name”, “Angel (ft. Regina Bell)”),
new XElement(“artist”, “DMX”),
new XElement(“album”, “…And Then There Was X”)),
new XElement(“track”,
new XAttribute(“id”, trackId++),
new XAttribute(“genre”, “Break Beat”),
new XAttribute(“time”, “6:16″),
new XElement(“name”, “Dreaming Your Dreams”),
new XElement(“artist”, “Hybrid”),
new XElement(“album”, “Wide Angle”)),
new XElement(“track”,
new XAttribute(“id”, trackId++),
new XAttribute(“genre”, “Break Beat”),
new XAttribute(“time”, “9:38″),
new XElement(“name”, “Finished Symphony”),
new XElement(“artist”, “Hybrid”),
new XElement(“album”, “Wide Angle”))));
//сохраняем наш документ
doc.Save(fileName);

Теперь в папке с нашей программой после запуска появится XML файл следующего содержания:

Who We Be RMX (feat. 2Pac)
DMX
The Dogz Mixtape: Who’s Next?!

Angel (ft. Regina Bell)
DMX
…And Then There Was X

Dreaming Your Dreams
Hybrid
Wide Angle

Finished Symphony
Hybrid
Wide Angle

Для создания подобного файла средствами XmlDocument кода понадобилось где-то раза в 2 больше. В коде выше мы воспользовались конструктором класса XDocument, который принимает в качестве параметра перечень дочерних элементов, которыми мы изначально хотим инициализировать документ. Используемый конструктор XElement принимает в качестве параметра имя элемента, который мы создаем, а так же перечень инициализирующих элементов. Удобно то, что мы в этих элементах можем задавать как новые XElement, так и XAttribute. Последние отрендретятся в наш файл как атрибуты самостоятельно. Если вам не нравится использоваться такую вложенность конструкторов и вы считаете такой код громоздким, то можно переписать в более традиционный вариант. Код ниже даст на выходе аналогичный XML файл:

XDocument doc = new XDocument();
XElement library = new XElement(“library”);
doc.Add(library);

//создаем элемент “track”
XElement track = new XElement(“track”);
//добавляем необходимые атрибуты
track.Add(new XAttribute(“id”, 1));
track.Add(new XAttribute(“genre”, “Rap”));
track.Add(new XAttribute(“time”, “3:24″));

//создаем элемент “name”
XElement name = new XElement(“name”);
name.Value = “Who We Be RMX (feat. 2Pac)”;
track.Add(name);

//создаем элемент “artist”
XElement artist = new XElement(“artist”);
artist.Value = “DMX”;
track.Add(artist);

//Для разнообразия распарсим элемент “album”
string albumData = “The Dogz Mixtape: Who’s Next?!”;
XElement album = XElement.Parse(albumData);
track.Add(album);
doc.Root.Add(track);

/*
*остальные элементы добавляем по аналогии
*/

//сохраняем наш документ
doc.Save(fileName);

Естественно выбирать необходимый способ нужно по ситуации.

Чтение данных из файла
Сейчас попробуем просто прочитать данные из уже полученного файла и вывести их в удобном для восприятия виде в консоль:

//задаем путь к нашему рабочему файлу XML
string fileName = “base.xml”;
//читаем данные из файла
XDocument doc = XDocument.Load(fileName);
//проходим по каждому элементу в найшей library
//(этот элемент сразу доступен через свойство doc.Root)
foreach (XElement el in doc.Root.Elements())
{
//Выводим имя элемента и значение аттрибута id
Console.WriteLine(“{0} {1}”, el.Name, el.Attribute(“id”).Value);
Console.WriteLine(” Attributes:”);
//выводим в цикле все аттрибуты, заодно смотрим как они себя преобразуют в строку
foreach (XAttribute attr in el.Attributes())
Console.WriteLine(” {0}”, attr);
Console.WriteLine(” Elements:”);
//выводим в цикле названия всех дочерних элементов и их значения
foreach (XElement element in el.Elements())
Console.WriteLine(” {0}: {1}”, element.Name, element.Value);
}

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

track 1
Attributes:
id=”1″
genre=”Rap”
time=”3:24″
Elements:
name: Who We Be RMX (feat. 2Pac)
artist: DMX
album: The Dogz Mixtape: Who’s Next?!
track 2
Attributes:
id=”2″
genre=”Rap”
time=”5:06″
Elements:
name: Angel (ft. Regina Bell)
artist: DMX
album: …And Then There Was X
track 3
Attributes:
id=”3″
genre=”Break Beat”
time=”6:16″
Elements:
name: Dreaming Your Dreams
artist: Hybrid
album: Wide Angle
track 4
Attributes:
id=”4″
genre=”Break Beat”
time=”9:38″
Elements:
name: Finished Symphony
artist: Hybrid
album: Wide Angle

Изменение данных
Попробуем пройтись по всем узлам library и увеличить аттрибут Id элемента track на 1.
(дальше писать объявление пути к файлу и результат вывода в консоль я приводить не буду, чтобы не перегружать лишней информацией статью, все компилировал, все работает:) ):

//Получаем первый дочерний узел из library
XNode node = doc.Root.FirstNode;
while (node != null)
{
//проверяем, что текущий узел – это элемент
if (node.NodeType == System.Xml.XmlNodeType.Element)
{
XElement el = (XElement)node;
//получаем значение аттрибута id и преобразуем его в Int32
int id = Int32.Parse(el.Attribute(“id”).Value);
//увеличиваем счетчик на единицу и присваиваем значение обратно
id++;
el.Attribute(“id”).Value = id.ToString();
}
//переходим к следующему узлу
node = node.NextNode;
}
doc.Save(fileName);

Теперь попробуем это сделать более правильным способом для наших задач:

foreach (XElement el in doc.Root.Elements(“track”))
{
int id = Int32.Parse(el.Attribute(“id”).Value);
el.SetAttributeValue(“id”, –id);
}
doc.Save(fileName);

Как видим – этот способ нам подошел больше.

Добавление новой записи
Добавим новый трек в нашу библиотеку, а заодно вычислим средствами LINQ следующий уникальный Id для трека:

int maxId = doc.Root.Elements(“track”).Max(t => Int32.Parse(t.Attribute(“id”).Value));
XElement track = new XElement(“track”,
new XAttribute(“id”, ++maxId),
new XAttribute(“genre”, “Break Beat”),
new XAttribute(“time”, “5:35″),
new XElement(“name”, “Higher Than A Skyscraper”),
new XElement(“artist”, “Hybrid”),
new XElement(“album”, “Morning Sci-Fi”));
doc.Root.Add(track);
doc.Save(fileName);

Вот таким подним запросом ко всем элементам вычисляется максимальное значение аттрибута id у треков. При добавлении полученное максимальное значение инкрементируем. Само же добавление элемента сводится к вызову метода Add. Обратите внимание, что добавляем элементы в Root, так как иначе нарушим структуру XML документа, объявив там 2 корневых элемента. Так же не забывайте сохранять ваш документ на диск, так как до момента сохранения никакие изменения в нашем XDocument не отразятся в XML файле.

Удаление элементов
Попробуем удалить все элементы исполнителя DMX:

IEnumerable tracks = doc.Root.Descendants(“track”).Where(
t => t.Element(“artist”).Value == “DMX”).ToList();
foreach (XElement t in tracks)
t.Remove();

В этом примере мы вначале выбрали все треки у который дочерний элемент artst удовлетворяет критерии, а потом в цикле удалили эти элементы. Важен вызов в конце выборки ToList(). Этим самым мы фиксируем в отдельном участке памяти все элементы, которые хотим удалить. Если же мы надумаем удалять из набора записей, по которому проходим непосредственно в цикле, мы получим удаление первого элемента и последующий NullReferenceException. Так что важно помнить об этом. По совету посмотреть профиль XaocCPS удалять можно и более простым способом:

IEnumerable tracks = doc.Root.Descendants(“track”).Where(
t => t.Element(“artist”).Value == “DMX”);
tracks.Remove();

В этом случае приводить к списку наш полученный результат вызовом функции ToList() не нужно. Почему этот способ не использовал изначально описал в комментарии :)

Немного дополнительных запросов к нашей базе треков
Отсортируем треки по продолжительности в обратном порядке:

IEnumerable tracks = from t in doc.Root.Elements(“track”)
let time = DateTime.Parse(t.Attribute(“time”).Value)
orderby time descending
select t;
foreach (XElement t in tracks)
Console.WriteLine(“{0} – {1}”, t.Attribute(“time”).Value, t.Element(“name”).Value);

Отсортируем элементы по жанру, исполнителю, названию альбома, названию трека:

IEnumerable tracks = from t in doc.Root.Elements(“track”)
orderby t.Attribute(“genre”).Value,
t.Element(“artist”).Value,
t.Element(“album”).Value,
t.Element(“name”).Value
select t;
foreach (XElement t in tracks)
{
Console.WriteLine(“{0} – {1} – {2} – {3}”, t.Attribute(“genre”).Value,
t.Element(“artist”).Value,
t.Element(“album”).Value,
t.Element(“name”).Value);
}

Простенький запрос, выводящий количество треков в каждом альбоме:

var albumGroups = doc.Root.Elements(“track”).GroupBy(t => t.Element(“album”).Value);
foreach (IGrouping a in albumGroups)
Console.WriteLine(“{0} – {1}”, a.Key, a.Count());

Выводы
После того как вы освоили пространство имен System.Xml для работы с XML на более низком уровне, смело переходите на использование System.Xml.Linq, надеюсь, написанная статья поможет это сделать быстрее, ведь не так страшен черт, как его рисуют. Как видно из примеров выше – многие вещи делать значительно проще, количество строк кода сокращается. Это дает нам очевидные преимущется, начиная со скорости разработки, заканчивая более легким сопровождением кода, написанного ранее.

72 comments to “Работаем с LINQ to XML”

  1. … [Trackback]…

    [...] Read More: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  2. … [Trackback]…

    [...] Read More here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  3. … [Trackback]…

    [...] Informations on that Topic: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  4. … [Trackback]…

    [...] Read More here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  5. … [Trackback]…

    [...] Informations on that Topic: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  6. … [Trackback]…

    [...] There you will find 64043 more Infos: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  7. … [Trackback]…

    [...] Read More Infos here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  8. … [Trackback]…

    [...] Read More: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  9. … [Trackback]…

    [...] There you will find 78774 more Infos: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  10. … [Trackback]…

    [...] Informations on that Topic: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  11. … [Trackback]…

    [...] Read More here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  12. chhota bheem games…

    Thank you so much for giving everyone an exceptionally splendid chance to read in detail from here. It really is so sweet plus jam-packed with a great time for me personally and my office mates to visit the blog the equivalent of thrice a week to find …

  13. Uhaul Coupons…

    Thank you a lot for giving everyone an extremely brilliant opportunity to read in detail from here. It is usually very kind plus packed with fun for me personally and my office peers to visit your web site the equivalent of three times weekly to study …

  14. … [Trackback]…

    [...] There you will find 64499 more Infos: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  15. … [Trackback]…

    [...] Read More: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  16. … [Trackback]…

    [...] Read More here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  17. … [Trackback]…

    [...] There you will find 69400 more Infos: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  18. … [Trackback]…

    [...] There you will find 63596 more Infos: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  19. … [Trackback]…

    [...] Read More here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  20. phoenix market place…

    Thanks a lot for giving everyone an extremely pleasant chance to read in detail from this blog. It is always very awesome plus full of fun for me personally and my office peers to visit your website nearly 3 times per week to read through the newest it…

  21. … [Trackback]…

    [...] Read More Infos here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  22. … [Trackback]…

    [...] Read More here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  23. apartment tel aviv…

    Thank you so much for providing individuals with an extremely nice chance to discover important secrets from this site. It is always very awesome plus full of a good time for me and my office mates to visit your web site on the least 3 times in a week …

  24. … [Trackback]…

    [...] Read More here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  25. been verified scam…

    Thank you so much for giving everyone a very superb possiblity to read from this site. It’s usually very great and as well , stuffed with fun for me personally and my office co-workers to visit your blog no less than three times in one week to study t…

  26. myanmar room…

    I’m impressed, I must say. Actually hardly ever do I encounter a weblog that’s each educative and entertaining, and let me tell you, you’ve gotten hit the nail on the head. Your concept is excellent; the problem is one thing that not sufficient people…

  27. … [Trackback]…

    [...] Read More: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  28. … [Trackback]…

    [...] Informations on that Topic: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  29. … [Trackback]…

    [...] There you will find 64068 more Infos: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  30. … [Trackback]…

    [...] There you will find 61280 more Infos: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  31. … [Trackback]…

    [...] Informations on that Topic: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  32. … [Trackback]…

    [...] Find More Informations here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  33. … [Trackback]…

    [...] Read More: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  34. … [Trackback]…

    [...] There you will find 64133 more Infos: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  35. … [Trackback]…

    [...] Informations on that Topic: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  36. … [Trackback]…

    [...] Read More: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  37. … [Trackback]…

    [...] Find More Informations here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  38. … [Trackback]…

    [...] Find More Informations here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  39. … [Trackback]…

    [...] Informations on that Topic: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  40. … [Trackback]…

    [...] Find More Informations here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  41. … [Trackback]…

    [...] Read More: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  42. … [Trackback]…

    [...] Read More here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  43. … [Trackback]…

    [...] Read More here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  44. … [Trackback]…

    [...] There you will find 78986 more Infos: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  45. … [Trackback]…

    [...] There you will find 76264 more Infos: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  46. … [Trackback]…

    [...] Informations on that Topic: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  47. … [Trackback]…

    [...] Informations on that Topic: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  48. … [Trackback]…

    [...] Read More here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  49. … [Trackback]…

    [...] Read More here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  50. … [Trackback]…

    [...] There you will find 74873 more Infos: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  51. … [Trackback]…

    [...] Read More here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  52. … [Trackback]…

    [...] There you will find 64270 more Infos: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  53. … [Trackback]…

    [...] There you will find 75089 more Infos: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  54. … [Trackback]…

    [...] Read More: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  55. … [Trackback]…

    [...] Read More here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  56. … [Trackback]…

    [...] Read More: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  57. … [Trackback]…

    [...] Read More: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  58. … [Trackback]…

    [...] Informations on that Topic: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  59. … [Trackback]…

    [...] There you will find 62196 more Infos: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  60. … [Trackback]…

    [...] Read More here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  61. … [Trackback]…

    [...] Informations on that Topic: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  62. … [Trackback]…

    [...] Read More: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  63. … [Trackback]…

    [...] Find More Informations here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  64. … [Trackback]…

    [...] Read More: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  65. … [Trackback]…

    [...] There you will find 77822 more Infos: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  66. … [Trackback]…

    [...] Read More: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  67. … [Trackback]…

    [...] Read More Infos here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  68. … [Trackback]…

    [...] Informations on that Topic: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  69. … [Trackback]…

    [...] Read More Infos here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  70. … [Trackback]…

    [...] There you will find 79228 more Infos: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  71. … [Trackback]…

    [...] Read More Infos here: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

  72. … [Trackback]…

    [...] Informations on that Topic: wiki.dodex.org/2009/03/03/работаем-с-linq-to-xml-3/ [...]…

Leave a comment

You need to log in to comment.

© 2008 З.П.И. благодарен WordPress за движок.