Атрибуты XML

68

Ранее уже упоминалось, что в 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);

Вот вывод этого кода:

Обращение к первому атрибуту элемента через свойство FirstAttribute

Вперед с помощью XAttribute.NextAttribute

Чтобы выполнить обход вперед по атрибутам элемента, обратитесь к свойству атрибута NextAttribute. Пример представлен ниже:

...
Console.WriteLine(firstEmployee.FirstAttribute.NextAttribute);

Обратите внимание, что для получения ссылки на первый атрибут используется свойство FirstAttribute, а затем на ней применяется NextAttribute. Результат можно видеть ниже:

Обращение к следующему атрибуту элемента через свойство NextAttribute

Если свойство атрибута NextAttribute равно null, значит, текущий атрибут у элемента является последним.

Назад с помощью XAttribute.PreviousAttribute

Чтобы выполнить обход атрибутов элемента в обратном направлении, обращайтесь к свойству атрибута PreviousAttribute. Пример представлен ниже:

...
Console.WriteLine(firstEmployee.FirstAttribute.NextAttribute.PreviousAttribute);

Обратите внимание, что свойства FirstAttribute и NextAttribute выстроены в цепочку, чтобы получить ссылку на второй атрибут, от которого выполняется шаг назад. Это должно привести обратно к первому атрибуту.

Если свойство PreviousAttribute равно null, значит, данный атрибут является у элемента первым.

Назад с помощью XElement.LastAttribute

Для получения доступа к самому последнему атрибуту элемента, чтобы затем выполнить обратный обход атрибутов, используйте свойство LastAttribute, как показано ниже:

...
Console.WriteLine(firstEmployee.LastAttribute);

В результате должен быть выведен атрибут age:

Обращение к последнему атрибуту элемента через свойство LastAttribute

XElement.Attribute()

Этот метод принимает имя атрибута и возвращает первый атрибут с указанным именем, если таковой существует. Ниже приведен пример:

...
Console.WriteLine(firstEmployee.Attribute("language").Value);

Для получения ссылки на атрибут language здесь используется метод Attribute. Затем с помощью свойства Value отображается значение атрибута. Вывод должен быть таким:

Обращение к атрибуту методом Attribute

Однако вместо получения значения атрибута через свойство 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);

Вывод будет таким:

Обращение ко всем атрибутам элемента методом Attributes

Модификация атрибутов

Для модификации атрибутов служат несколько методов и свойств, которые описаны ниже.

Добавление атрибутов

Как уже было указано, существует фундаментальное отличие в способах обработки атрибутов между интерфейсами 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. Вот результат:

Применение SetAttributeValue для добавления, удаления и обновления атрибутов
Пройди тесты
Лучший чат для C# программистов