Атрибуты XML
68LINQ --- LINQ to XML --- Атрибуты XML
Ранее уже упоминалось, что в API-интерфейсе LINQ to XML атрибуты реализованы классом XAttribute, и в отличие от W3C XML DOM API, они не унаследованы от узла. Поэтому они не имеют отношений наследования с элементами. Однако в LINQ to XML работать с ними так же просто, как и с элементами. Давайте посмотрим, как это делается.
Создание и обход атрибутов
Атрибуты создаются точно так же, как элементы и большинство других классов LINQ to XML с помощью XAttribute".
Для обхода атрибутов используются свойства XElement.FirstAttribute, XElement.LastAttribute, XAttribute.NextAttribute и XAttribute.PreviousAttribute, a также методы XElement.Attribute и XElement.Attributes. Все они описаны в последующих разделах.
Вперед с помощью XElement.FirstAttribute
Получить доступ к атрибутам элемента можно, обратившись к его первому атрибуту через свойство элемента FirstAttribute. Ниже показан пример:
// Это используется для сохранения ссылки на один из элементов дерева XML
XElement firstEmployee;
XDocument xDoc = new XDocument(
new XElement("Employees", firstEmployee =
new XElement("Employee",
new XAttribute("type", "Programmer"),
new XAttribute("language", "Russian"),
new XAttribute("age",26),
new XElement("FirstName", "Alex"),
new XElement("LastName", "Erohin"))));
Console.WriteLine(firstEmployee.FirstAttribute);
Вот вывод этого кода:
Вперед с помощью XAttribute.NextAttribute
Чтобы выполнить обход вперед по атрибутам элемента, обратитесь к свойству атрибута NextAttribute. Пример представлен ниже:
...
Console.WriteLine(firstEmployee.FirstAttribute.NextAttribute);
Обратите внимание, что для получения ссылки на первый атрибут используется свойство FirstAttribute, а затем на ней применяется NextAttribute. Результат можно видеть ниже:
Если свойство атрибута NextAttribute равно null, значит, текущий атрибут у элемента является последним.
Назад с помощью XAttribute.PreviousAttribute
Чтобы выполнить обход атрибутов элемента в обратном направлении, обращайтесь к свойству атрибута PreviousAttribute. Пример представлен ниже:
...
Console.WriteLine(firstEmployee.FirstAttribute.NextAttribute.PreviousAttribute);
Обратите внимание, что свойства FirstAttribute и NextAttribute выстроены в цепочку, чтобы получить ссылку на второй атрибут, от которого выполняется шаг назад. Это должно привести обратно к первому атрибуту.
Если свойство PreviousAttribute равно null, значит, данный атрибут является у элемента первым.
Назад с помощью XElement.LastAttribute
Для получения доступа к самому последнему атрибуту элемента, чтобы затем выполнить обратный обход атрибутов, используйте свойство LastAttribute, как показано ниже:
...
Console.WriteLine(firstEmployee.LastAttribute);
В результате должен быть выведен атрибут age:
XElement.Attribute()
Этот метод принимает имя атрибута и возвращает первый атрибут с указанным именем, если таковой существует. Ниже приведен пример:
...
Console.WriteLine(firstEmployee.Attribute("language").Value);
Для получения ссылки на атрибут language здесь используется метод Attribute. Затем с помощью свойства Value отображается значение атрибута. Вывод должен быть таким:
Однако вместо получения значения атрибута через свойство Value можно было бы просто привести атрибут к типу string.
XElement.Attributes()
Доступ сразу ко всем атрибутам элемента можно получить через метод Attributes. Этот метод возвращает последовательность объектов XAttribute. Ниже показан пример:
// Это используется для сохранения ссылки на один из элементов дерева XML
XElement firstEmployee;
XDocument xDoc = new XDocument(
new XElement("Employees", firstEmployee =
new XElement("Employee",
new XAttribute("type", "Programmer"),
new XAttribute("language", "Russian"),
new XAttribute("age",26),
new XElement("FirstName", "Alex"),
new XElement("LastName", "Erohin"))));
foreach (XAttribute attr in firstEmployee.Attributes())
Console.WriteLine(attr);
Вывод будет таким:
Модификация атрибутов
Для модификации атрибутов служат несколько методов и свойств, которые описаны ниже.
Добавление атрибутов
Как уже было указано, существует фундаментальное отличие в способах обработки атрибутов между интерфейсами W3C XML DOM API и LINQ to XML. В W3C API атрибут — это дочерний узел по отношению к узлу, атрибутом которого он является. В LINQ to XML атрибуты не являются дочерними узлами такого узла. Вместо этого атрибуты представляют собой пары "имя-значение", доступ к которым осуществляется через метод Attributes элемента либо через свойство FirstAttribute. Важно помнить об этом.
Тем не менее, работа с атрибутами очень похожа на работу с элементами. Методы и свойства атрибутов подобны методам и свойствам, предназначенным для работы с элементами. Для добавления атрибута к элементу используются следующие методы:
XElement.Add()
XElement.AddFirst()
XElement.AddBeforeThis()
XElement.AddAfterThis()
Данные методы полностью идентичны методам, описанным в предыдущей статье, поэтому для справки обратитесь к ней.
Удаление атрибутов
Удаление атрибутов осуществляется либо методом XAttribute.Remove, либо IEnumerable<T>.Remove — в зависимости от того, нужно удалить единственный атрибут или последовательность атрибутов.
В дополнение к описанным выше способам удаления атрибутов загляните в раздел "XElement.SetAttributeValue()" далее в этой статье.
- XElement.Remove()
Подобно XNode, класс XAttribute также имеет метод Remove. Пример его вызова представлен ниже:
// Это используется для сохранения ссылки на один из элементов дерева XML XElement firstEmployee; Console.WriteLine("Перед удалением атрибута:"); XDocument xDoc = new XDocument( new XElement("Employees", firstEmployee = new XElement("Employee", new XAttribute("type", "Programmer"), new XAttribute("language", "Russian"), new XAttribute("age",26), new XElement("FirstName", "Alex"), new XElement("LastName", "Erohin")))); Console.WriteLine(xDoc + "\n\nПосле удаления атрибута: "); firstEmployee.Attribute("type").Remove(); Console.WriteLine(xDoc);
Как видите, с помощью метода Attribute получается ссылка на атрибут, подлежащий удалению, а затем на ней вызывается метод Remove. Ниже показан результат работы этого примера:
Обратите внимание, что атрибут type исчез.
- IEnumerable<T>.Remove()
Точно так же, как метод IEnumerable<T>.Remove позволяет удалять последователеность узлов, с его помощью можно удалить и все атрибуты элемента, как показано в примере ниже:
... firstEmployee.Attributes().Remove(); ...
В приведенном примере вызывается метод Attributes, возвращающий последовательность атрибутов элемента, на котором вызван, а затем на этой возвращенной последовательности — метод Remove, чтобы удалить их все. Все выглядит простым и интуитивно понятным. Вот результат:
Как видите, атрибуты исчезли.
Обновление атрибутов
Для обновления значения атрибута используется свойство XAttribute.Value.
Обновление значения атрибута легко осуществляется через его свойство Value. Пример приведен ниже:
// Это используется для сохранения ссылки на один из элементов дерева XML
XElement firstEmployee;
Console.WriteLine("Перед изменением атрибутов:");
XDocument xDoc = new XDocument(
new XElement("Employees", firstEmployee =
new XElement("Employee",
new XAttribute("type", "Programmer"),
new XAttribute("language", "Russian"),
new XAttribute("age",26),
new XElement("FirstName", "Alex"),
new XElement("LastName", "Erohin"))));
Console.WriteLine(xDoc + "\n\nПосле изменения атрибутов: ");
firstEmployee.Attribute("type").Value = "Editor";
firstEmployee.Attribute("language").Value = "English";
firstEmployee.Attribute("age").Value = "22";
Console.WriteLine(xDoc);
Обратите внимание, что для получения ссылки на атрибут используется метод Attribute. Результат работы этого кода выглядит следующим образом:
Как видите значения атрибутов изменились.
XElement.SetAttributeValue()
Сохраняя симметрию с методами элементов, можно ожидать, что метод SetAttributeValue должен быть столь же мощным, что и метод SetElementValue. Так оно и есть. Метод XElement.SetAttributeValue() обладает способностью добавлять, удалять и обновлять атрибут.
Передача этому методу имени несуществующего атрибута приводит к его добавлению. Передача имени существующего атрибута со значением, отличным от null, вызывает обновление значения указанного атрибута. Передача имени существующего атрибута и значения null вызовет удаление соответствующего атрибута. Примеры всех трех случаев приведены в примере ниже:
// Это используется для сохранения ссылки на один из элементов дерева XML
XElement firstEmployee;
Console.WriteLine("Перед изменением атрибутов:");
XDocument xDoc = new XDocument(
new XElement("Employees", firstEmployee =
new XElement("Employee",
new XAttribute("type", "Programmer"),
new XAttribute("language", "Russian"),
new XAttribute("age",26),
new XElement("FirstName", "Alex"),
new XElement("LastName", "Erohin"))));
Console.WriteLine(xDoc + "\n\nПосле изменения атрибутов: ");
// Обновим атрибут type
firstEmployee.SetAttributeValue("type", "Editor");
// Удалим атрибут language
firstEmployee.SetAttributeValue("language", null);
// Создадим новый атрибут nickName
firstEmployee.SetAttributeValue("nickName", "alexsave");
Console.WriteLine(xDoc);
Как видите, в этом примере сначала обновляется значение существующего атрибута, затем добавляется новый атрибут и, наконец, удаляется существующий атрибут за счет передачи значения null. Вот результат: