Как получить значение тега вложенного элемента?

90
10 апреля 2021, 03:10

Есть xml-файл с элементом <casdo:ProcedureCode >78</casdo:ProcedureCode>, который есть где-то вначале документа:

<casdo:ProcedureCode >78</casdo:ProcedureCode>

и есть где-то в середине документа:

<cacdo:ProcedureDetails>
  <casdo:ProcedureCode >78</casdo:ProcedureCode>
</cacdo:ProcedureDetails>

Правда, во втором случае он вложен в другой элемент.

Использую XmlTextReader для парсинга. Считываю значение "78" и передаю его объекту Text. И вот тут проблема: если бы тег casdo:ProcedureCode в документе повторялся бы один раз, проблем бы не было.

Как мне исключить считывание значения тега первого (невложенного) элемента, т.е. reader должен проигнорировать первый тег casdo:ProcedureCode, а второй считать?

Весь код примерно такой:

public Text text;     
public void LoadData()
{
    if (File.Exists("C:/Users/xml/1.xml"))
    {
        XmlTextReader reader = new XmlTextReader("C:/Users/xml/1.xml");
        while (reader.Read())
        {
            if (reader.IsStartElement() && !reader.IsEmptyElement)
            {
                switch (reader.Name)
                {
                    ...
                    case "casdo:ProcedureCode": // как добавить условие, что "и этот элемент вложен в  cacdo:ProcedureDetails"?
                        text.text = reader.ReadString();
                        break;
                }
            }
        }
        reader.Close();
    }
    else
    {
        Debug.Log("указанный файл или путь к нему не существует!");
    }
Answer 1

Хорошо бы знать, какие ещё данные вы получаете из этого файла.

Если нужно просто получить значение из узла ProcedureCode, вложенного в узел ProcedureDetails, то это делается элементарно так:

using (var reader = XmlReader.Create("test.xml"))
{
    if (reader.ReadToFollowing("cacdo:ProcedureDetails"))
    {
        reader.ReadToFollowing("casdo:ProcedureCode");
        var text = reader.ReadElementContentAsString();
        Console.WriteLine(text);
    }
}

Обратите внимание: XmlReader создаётся вызовом метода Create - это рекомендованный в документации способ вместо использования устаревшего класса XmlTextReader.

Сам ридер обёрнут в конструкцию using - это автоматически вызовет метод Dispose, что закроет ридер и освободит все ресурсы, даже в случае исключения.

XmlReader имеет множество полезных методов. Один из них ReadToFollowing - он перемещает нас сразу к нужному элементу.

Однако, думаю, вам нужно не просто пропускать элементы по пути к нужному, но как-то их обрабатывать.

Можно использовать дополнительную переменную-флаг.

bool insideProcedureDetails = false;
using (var reader = XmlReader.Create("test.xml"))
{
    while (reader.Read())
    {
        if (reader.IsStartElement())
        {
            switch (reader.Name)
            {
                case "cacdo:ProcedureDetails":
                    insideProcedureDetails = true;
                    break;
                case "casdo:ProcedureCode":
                    if (insideProcedureDetails)
                    {
                        var text = reader.ReadElementContentAsString();
                        Console.WriteLine(text);
                        insideProcedureDetails = false;
                    }
                    break;
            }
        }
    }
}

получить значение из узла ProcedureCode, вложенного в узел ProcedureDetails, вложенного в узел Procedure

Всё то же самое. Просто добавляем ещё одну булеву переменную и ещё одну ветку case.

bool insideProcedure = false;
bool insideProcedureDetails = false;
using (var reader = XmlReader.Create("test.xml"))
{
    while (reader.Read())
    {
        if (reader.IsStartElement())
        {
            switch (reader.Name)
            {
                case "Procedure":
                    insideProcedure = true;
                    break;
                case "cacdo:ProcedureDetails":
                    insideProcedureDetails = true;
                    break;
                case "casdo:ProcedureCode":
                    if (insideProcedure && insideProcedureDetails)
                    {
                        var text = reader.ReadElementContentAsString();
                        Console.WriteLine(text);
                        insideProcedure = false;
                        insideProcedureDetails = false;
                    }
                    break;
            }
        }
    }
}
READ ALSO
Ошибка в NancyFx: Cannot apply indexing with [] to an expression of type &#39;method group&#39;

Ошибка в NancyFx: Cannot apply indexing with [] to an expression of type 'method group'

Я пытаюсь создать класс (модуль Nancy) и получаю следующую ошибку:

104
Как добавить decimal в базу данных Access через EF Core?

Как добавить decimal в базу данных Access через EF Core?

Имем сущность Contracts со свойством SalaryДобавление в базу с помощью метода Add()

111
Пропадает заголовок запроса

Пропадает заголовок запроса

Отправляю запрос с заголовком AutorizationЕсли смотреть данные о запросе через кастомный middleware, то он там есть

118
Механизм работы виртуальных методов в C#

Механизм работы виртуальных методов в C#

Мне немного не ясен механизм работы виртуальных методов в C#Знаю, что для каждого класса, имеющего виртуальные методы, есть своя таблица виртуальных...

89