Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.89/9: Рейтинг темы: голосов - 9, средняя оценка - 4.89
2 / 2 / 0
Регистрация: 27.11.2015
Сообщений: 36
.NET 4.x

Linq to XML

19.10.2018, 13:59. Показов 2555. Ответов 32
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет! Возник следующий вопрос. Делаю запрос к Web-сервису и в ответ получаю XML вида:

XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[COLOR="Red"]<sender>TestSender</msg_sender>
       <receiver>TestRec</msg_receiver>[/COLOR]
       <type>IN_REC</msg_type>
       <msg_info>
             <response_info>
                    <Header>
                           [COLOR="red"]<MsgId>ARM655655</MsgId>
                           <MsgTime>2018-10-16T17:44:17</MsgTime>
[/COLOR]                           <Status>P</Status>
                    </Header>
                    <Body>
                           [COLOR="red"]<UserName>Test</UserName>
                           <ClaimID>CL6555</ClaimID>
[/COLOR]                                <StsRsn>
                                       <Prtry>DD10</Prtry>
                                </StsRsn>
                    </Body>
             </response_info>
       </msg_info>"
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
19.10.2018, 13:59
Ответы с готовыми решениями:

Подсчитать количтво нодов в XML при помощи LINQ to XML
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt; &lt;Root&gt; &lt;host&gt; 192.168.1.1 &lt;/host&gt; &lt;host&gt; 192.168.1.3 &lt;/host&gt; &lt;/Root&gt; как...

Объединение 2 xml файлов по ключу в 1 xml с использованием linq
День добрый. Я уже отписывался в другой теме с объединением 2 xml, но увы тот метод для меня слишком сложен. Видел на форумах ребята...

Создание xml документа посредством LINQ to XML
Добрый день. Мне необходимо создать xml-документ который будет включать следующие элементы: &lt;Envelope...

32
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,177
Записей в блоге: 2
22.10.2018, 16:24
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Estenity Посмотреть сообщение
И я хочу засунуть в обычную локальную переменную, например, имя Body.
При этом:
1) Я, например, знаю, что он имеет имя Body
2) Я только знаю, что он самый верхний по уровню
Здесь, наверное, у Вас описка. Вероятно Вы хотели написать 1) Я, например, НЕ знаю, что он имеет имя Body
Корневой элемент получают из свойства Root XDocument'а - это уже написал Вам AlexP11223 для консоли.
Для переменной это будет так
C#
1
2
3
            XElement root = doc.Root; // Имя переменной root - условно. Можете назвать как угодно.
            XName rootXName = doc.Root.Name; // Имя корневого элемента в формате XName 
            string rootName = doc.Root.Name.LocalName; // Имя корневого элемента в формате string
Добавлено через 9 минут
Получение корневого элемента таким образом
C#
1
              XElement root = doc.Element("Body"); // В root - корневой элемент с именем Body если он есть
Нужно для проверок на ошибки и корректность загруженных в doc XML данных. Если корневой элемент имеет другое имя, то root == null. Проверив это условие, Вы можете дать предупреждение об ошибке, так как отличие в имени корневого элемента обычно означает и отличия в структуре последующих данных.
1
 Аватар для AlexP11223
141 / 110 / 30
Регистрация: 20.04.2011
Сообщений: 582
22.10.2018, 16:28
Цитата Сообщение от Estenity Посмотреть сообщение
Но это коллекция, а я если я знаю, что он дочерний точно 1.
.First()
1
Эксперт JS
6497 / 3908 / 2006
Регистрация: 14.06.2018
Сообщений: 6,781
22.10.2018, 16:59
Второй элемент с неизвестным именем тоже прикольно вытаскивается
C#
1
2
3
4
5
6
7
8
9
10
            var o = new Claim {
                Sender = root.Element("sender").Value,
                Receiver= root.Element("receiver").Value,
                MsgID=header.Element("MsgId").Value,
                MsgTime=DateTime.Parse(header.Element("MsgTime").Value),
                Status = header.Element("Status").Value[0],
                ClaimID = body.Element("ClaimID").Value,
                Prtry = body.Element("StsRsn").Elements().First().Value,
                AddStInf = body.Element("StsRsn").Elements().ElementAt(1).Value,
            };
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,177
Записей в блоге: 2
22.10.2018, 17:05
Цитата Сообщение от Estenity Посмотреть сообщение
А если я знаю, что он у меня дочерний от самого верхнего и он только 1.
Я понимаю, что есть вариант:
Вариантов может множество. Здесь важен ещё тот факт - откуда у Вас этот XML файл?
Если Вы его формируете сами, то это одно. Вы можете задать жёсткую структуру и соответствующую его обработку.
Но если источник файла сторонний, Вы должны как защитить своё приложение от исключений, так как Вы не можете гарантировать стабильность структуры XML файла.
Поэтому, в этом случае, перед созданием объекта с нужными данными, Вам надо сначала проверить все ли данные в полученном файле есть.
Так же, я заметил, что имена всех дочерних элементов уникальны. Можно тогда использовать получение данных элемента не зависимо от его вложенности. Это даст защиту на случай незначительных модернизаций структуры файла. Для это можно использовать XmlReader.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
            string test = @"
    <root>
       <sender>TestSender</sender>
       <receiver>TestRec</receiver>
       <type>IN_REC</type>
       <msg_info>
             <response_info>
                    <Header>
                           <MsgId>ARM655655</MsgId>
                           <MsgTime>2018-10-16T17:44:17</MsgTime>
                           <Status>P</Status>
                    </Header>
                    <Body>
                          <UserName>Test</UserName>
                          <ClaimID>CL6555</ClaimID>
                          <StsRsn>Example<Prtry>DD10</Prtry>
                                  <AddStInf>Принят</AddStInf>
                       </StsRsn>
                    </Body>
             </response_info>
       </msg_info>
    </root>";
 
            XmlReader rdr = XmlReader.Create(new System.IO.StringReader(test));
            while (rdr.Read())
            {
                if (rdr.NodeType == XmlNodeType.Element)
                {
                    Console.Write("\r\n" + rdr.LocalName );
                }
                if (rdr.NodeType == XmlNodeType.Text )
                {
                    Console.Write(" = " + rdr.Value);
                }
            }
Добавлено через 1 минуту
Цитата Сообщение от amr-now Посмотреть сообщение
Второй элемент с неизвестным именем тоже прикольно вытаскивается
Ага - токо если его нет выйдет исключение.
1
2 / 2 / 0
Регистрация: 27.11.2015
Сообщений: 36
23.10.2018, 12:53  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
надо сначала проверить все ли данные в полученном файле есть.
Да, интересный вопрос.
А как ее решить?

Добавлено через 14 минут
На просторах интернета есть решение вида:
C#
1
2
3
4
public static string GetElementValue(this XElement element)
{
    return element != null ? element.Value : string.Empty;
}
Работает, но что не нравится.
При создании объекта т.е:

C#
1
2
3
4
5
6
7
8
9
10
11
Claim claim = new Claim()
            {
                Sender = root.Element("sender").Value,
                Receiver = root.Element("receiver").Value,
               MsgID  = Header.Element("MsgId").Value,
               MsgTime  = DateTime.Parse( Header.Element("MsgTime").Value),
               Status  = Header.Element("Status").Value[0],
                ClaimID = Body.Element("ClaimID").Value,
                Prtry = StsRsn.Element("Prtry").Value,
                AddStInf = StsRsn.Element("AddStInf").Value
            };
Приходится оборачивать каждый вызов .Element(). Как лучше обрабатывать?
0
Эксперт JS
6497 / 3908 / 2006
Регистрация: 14.06.2018
Сообщений: 6,781
23.10.2018, 12:54
Estenity, проще всего пойти по репе настучать отправителю ))
Вообще вопросы формата согласовываются в административном порядке.
Или если воруем данные из интернета, то подстраиваемся под формат "As is".
0
2 / 2 / 0
Регистрация: 27.11.2015
Сообщений: 36
23.10.2018, 12:55  [ТС]
Цитата Сообщение от amr-now Посмотреть сообщение
проще всего пойти по репе настучать отправителю
Есть необязательные узлы, вот их приходится обрабатывать
0
Эксперт JS
6497 / 3908 / 2006
Регистрация: 14.06.2018
Сообщений: 6,781
23.10.2018, 12:57
Estenity, это должно быть согласовано в административном порядке, и не быть нежданчиком для разработчика.
0
2 / 2 / 0
Регистрация: 27.11.2015
Сообщений: 36
23.10.2018, 13:00  [ТС]
Цитата Сообщение от amr-now Посмотреть сообщение
согласовано в административном порядке
Увы, не я это согласовываю)
Но разве это не достаточно стандартная ситуация, когда какой-то узел отсутствует в связи с отсутствием информации?
0
Эксперт JS
6497 / 3908 / 2006
Регистрация: 14.06.2018
Сообщений: 6,781
23.10.2018, 13:04
Estenity, это нестандартная ситуация.
Возможность отсутствия чего-то обговаривается.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,177
Записей в блоге: 2
23.10.2018, 13:34
Цитата Сообщение от Estenity Посмотреть сообщение
а, интересный вопрос.
А как ее решить?
На просторах интернета есть решение вида:
Вариантов решения множество. Но не один не даст полной адаптации к возможным несогласованным изменениям структуры файла, данных.
Один из способов, для данной ситуации, получать данные не через XDocument.Element , а используя XmlReader - это даст защиту от изменения вложенности элементов.
Так же в подобном случае, я делал получение данных не только из элементов, но и одноимённых атрибутов. Такой способ является стандартным для WPF.
Ещё обязательно надо предусмотреть дефолтные значения в случае отсутствия таковых в полученных данных.

Так как всё это имеет отношение только к созданию объекта класса Claim и не имеет отношение к остальному приложению, всё это надо прописать в статическом методе класса, возвращающего объект в случае если его можно создать из этих данных. Класс должен выглядеть примерно так
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
    public class Claim
    {
        public string Sender { get; private set; }
        public string Receiver { get; private set; }
        public string MsgID { get; private set; }
        public DateTime MsgTime { get; private set; }
        public char Status { get; private set; }
        public string ClaimID { get; private set; }
        public string Prtry { get; private set; }
        public string AddStInf { get; private set; }
 
        private Claim() { }
 
        static public Claim CreateFromXML(XElement xElement)
        {
            If (.....) return null;// Проверка допустимости данных, если недопустимы возвращает null
 
            // Получение и подготовка данных
 
            string sender = ....
            string receiver = ....
            string msgID = ....
            DateTime msgTime = ....
            char status = ....
            string claimID = ....
            string prtry = ....
            string addStInf = ....
                ;
 
            // Возврат нового объекта с извлечёнными данными
 
            return new Claim()
            {
                Sender = sender,
                Receiver = receiver,
                MsgID = msgID,
                MsgTime = msgTime,
                Status = status,
                ClaimID = claimID,
                Prtry = prtry,
                AddStInf = addStInf
            }
        }
    }
А его использование так
C#
1
2
3
4
5
            Claim claim = Claim.CreateFromXML(xElement);
            if (claim == null)
            {
                // Действия если объект не создан
            }
1
2 / 2 / 0
Регистрация: 27.11.2015
Сообщений: 36
23.10.2018, 15:14  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
C#
1
If (.....) return null;// Проверка допустимости данных, если недопустимы возвращает null
Вот тут можно немного поподробнее?
Не совсем понял, что тут надо проверять. Наличие необязательных узлов? Если да, то таким образом?

C#
1
2
3
4
5
6
7
8
9
 
string msgID = null;
var nameAttribute = xElement.Descendants("Header").Select(b => b.Attribute("MsgId"))
                                        .FirstOrDefault();
 
                if (nameAttribute != null)
                {
                    msgID = nameAttribute.Value;
                }
Просто это, получается для каждого такого необязательного узла (коих около 10) довольно большая проверка, или нет?

Добавлено через 44 минуты
Все это, конечно, можно обернуть в метод и выглядит уже лучше, но опять же вызывать для каждого узла метод проверки
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,177
Записей в блоге: 2
23.10.2018, 15:48
Цитата Сообщение от Estenity Посмотреть сообщение
Вот тут можно немного поподробнее?
Не совсем понял, что тут надо проверять. Наличие необязательных узлов? Если да, то таким образом?
Абстрактно трудно сказать. Это же зависит от того как Вы собираетесь использовать объекты этого класса, какие данные обязательны, а какие в случае отсутствия можно заменить дефолтными значениями.
Я могу только привести в пример один из своих алгоритмов.
  1. Устанавливаю в нуль при объявлении все переменные созданные для инициализации свойств объекта.
  2. Ищу по дереву данные в атрибутах
  3. Ищу по дереву данные в элементах,
  4. Использую какой-нибудь алгоритм для разрешения конфликта множественности данных. В простейшем случае, беру те, которые нашлись первыми
  5. Проверяю все ли обязательные данные заполнены (проверка на null), если не заполнены, то выхожу без создания объекта
  6. Заполняю неустановленные необязательные данные дефолтными значениями.
  7. Выхожу с созданием и возвратом нового объекта с заполненными свойствами.

Добавлено через 9 минут
Цитата Сообщение от Estenity Посмотреть сообщение
Просто это, получается для каждого такого необязательного узла (коих около 10) довольно большая проверка, или нет?
Все это, конечно, можно обернуть в метод и выглядит уже лучше, но опять же вызывать для каждого узла метод проверки
Но так обычно и бывает. Код проверяющий корректность данных по объёму в несколько раз превышает код получения данных.
Получить данные просто - считал и присвоил.
А корректность данных намного сложнее, надо установить все возможные варианты сочетания данных, их отсутствия и проверить их допустимость.
И делать это надо, конечно, не в основном коде, а в методе класса. Обязательно в статическом, а не в конструкторе. Так как конструктор сначала создаёт объект, а потом только начинает работу. А в алгоритме надо предусмотреть вариант, когда невозможно с этими данными создать объект.

Всё это делается, для того чтобы в дальнейшем можно было использовать этот класс и его объекты в приложении без больших заморочек и уверенностью, что раз объект создан, то данные в нём корректны.

Добавлено через 9 минут
Вот допустим простенький класс из реального моего приложения
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
    /// <summary>Класс для строк дополнительной информации</summary>
    public class FieldClass : OnPropertyChangedClass
    {
        #region Секция основных Public свойств
        private string _name;
        private string _value;
 
        /// <summary>Возвращает/устанавливает Имя строки</summary>
        public string Name { get => _name; set { _name = value; OnPropertyChanged("Name"); } }
 
        /// <summary>Возвращает/устанавливает Содержание строки</summary>
        public string Value { get => _value; set { _value = value; OnPropertyChanged("Value"); } }
 
        /// <summary>Возвращает/устанавливает Случайное число используется для хеш-кода строки</summary>
        private int RandomID { get; set; }
        #endregion
 
        #region Секция конструкторов
        /// <summary>Конструктор по умолчанию. Заполняет только поле RandomID.</summary>
        private FieldClass() => RandomID = new Random().Next();
 
        /// <summary>Конструктор с параметрами.</summary>
        public FieldClass(string NewName, string NewValue) { Name = NewName; Value = NewValue; RandomID = new Random().Next();}
        
        /// <summary>Статический метод создания новой строки из XElement</summary>
        /// <param name="myXElem">XElement с соответсвующим содержанием</param>
        public static FieldClass CreateFromXML(XElement myXElem)
            => myXElem?.Name != "Field"
                ? null
                : new FieldClass(myXElem.Attribute("Name").Value, myXElem.Attribute("Value").Value);
        #endregion
 
        #region Секция методов взаимодействия
        /// <summary>Метод - возвращает новую строку с копией содержания </summary>
        public FieldClass CopyTo() => new FieldClass { Name = Name, Value = Value };
 
        /// <summary>Метод - возвращает новый XElement с данными строки</summary>
        public XElement CopyToXML()
            => Name==null || Value==null
            ? null
            : new XElement("Field", new XAttribute("Name", Name), new XAttribute("Value", Value));
        #endregion
 
        #region Секция переопределения методов
        /// <summary>Переопределённый метод - возвращает Хеш-код от содержимого</summary>
        public override int GetHashCode() => (Name + Value).GetHashCode();
 
        /// <summary>Переопределённый метод сравнения содержимого строк</summary>
        public override bool Equals(object obj)
            => (obj is FieldClass m) ? m.Name == Name && m.Value == Value : false;
        #endregion
    }
Из 52 строк кода - получение данных только одна строка 30. 52 - это даже без учёта кода базового класса OnPropertyChangedClass

Добавлено через 4 минуты
20 строк - это комментарии и директивы препроцессора. А без них тоже нельзя. Иначе код будет непрозрачным и трудно модернезируемым.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
23.10.2018, 15:48

Создание документа XML через LINQ-to-XML
как создать новый документ xml через LINQ-to-xml XDocument doc =new XDocument(&quot;name.xml&quot;,Encoding.UTF8); ...

Linq to XML парсинг
Доброе утро, уважаемые форумчане, подскажите пожалуйста по Linq: Есть файл XML: &lt;?xml version=&quot;1.0&quot;...

Разбор XML LINQ
есть XML в котором есть такой элемент &lt;N&gt; &lt;I Name=&quot;VASYA&quot; Old=&quot;99&quot; Life=&quot;Moscow&quot;&gt;&lt;/I&gt; &lt;I Name=&quot;Oleg&quot; Old=&quot;88&quot;...

Не работает запрос linq к xml
Пытаюсь распарсить приведенный ниже XML документ. Код не работает, но, если я редактирую XML(удаляю самый первый родительский тег: Orders...

LINQ to XML - поиск по атрибуту
Здравствуйте хотелось бы попросить помощи в одном вопросе. Есть XML файл, записываю в него данные так: XDocument doc = new...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
33
Ответ Создать тему
Новые блоги и статьи
Особенности gif сгенерированных в Си
russiannick 21.10.2026
Рассмотрим генерацию gif файлов, которые в Си имеют свои особенности. Gif представляет собой графический формат популярный в интернете. Посмотрим на палитру. Gif файл сгенерированный в си отличается. . .
FPS контроллер с анимированными Y-Bot и 3D-звуком miniaudio (Box3D, Recast, BehaviorTree.CPP, ozz-animation, ImGui, OpenGL и SDL3)
8Observer8 18.10.2026
Содержание блога | English Version Полное мультиплатформенное руководство по стартовому проекту с FPS-контроллером игрока, анимированными роботами Y-Bot с 4-слойным блендингом, 3D-физикой Box3D,. . .
Локальный http сервер
Argus19 17.10.2026
Локальный http сервер На работе, на двух локальных компьютерах круглосуточно работают программы опроса приборов с записью в книги Excel,которые раз в сутки записываются на сервер компании. Т. к. . . .
Копировать Windows на новый диск на UEFI
damix 17.10.2026
https:/ / uriesk. wordpress. com/ 2016/ 11/ 01/ move-window-10-to-ssd-on-a-uefi-dualboot-system-with-basic-linux-tools/ TL DR Вставляем диск, а старый подключаем через переходник, грузимся с лайва. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru