Как получить доступ к различным элементам XML?

У меня есть XML, который содержит различную информацию о FlightPlan. Мне нужно взять данные этого плана полета с пометкой «RoutePoints». Пример ниже - это псевдокод для представления структуры. Символ «+» означает, что раздел может быть расширен.

    <RoutePoints>
      +<a:anyType z:Id = "411" i:type = "RoutePointTakeOff">
      +<a:anyType z:Id = "472" i:type = "RoutePoint">
      +<a:anyType z:Id = "518" i:type = "RoutePoint">
      <a:anyType z:Ref = "349" i:nil = "true"/>
      <a:anyType z:Ref = "272" i:nil = "true"/>
      +<a:anyType z:Id = "576" i:type = "RoutePoint">
      +<a:anyType z:Id = "638" i:type = "RoutePointLanding">
    </RoutePoints>

Потому что у меня разные типы элементов, которые нужно обрабатывать по-разному. Я попытался использовать инструмент foreach для доступа к этим элементам, пример ниже:

foreach ( var routes in document.Descendants("RoutePoints") ){
    foreach ( var points in routes.Elements() ) {
        if ( points.Attributes(i+"type").First().Value == "RoutePoint") {
            //Processing..
        }
        if ( points.Attributes(i+"type").First().Value == "RoutePointTakeOff") {
            //Processing..
        }
        if ( points.Attributes(i+"nil").First().Value == "true") {
            //Processing..
        }
        if ( points.Attributes(i+"type").First().Value == "RoutePointLanding") {
            //Processing..
        }
    }
}

Когда предложение if проверяет атрибуты для сравнения значения, а оно не существует, например, проверяет значение RoutePointTakeOff, и оно не существует, потому что это значение находится в первой строке, а теперь проверяется во второй строке.

Мне нужно взять элемент, информация, которую мне нужно обработать, находится внутри элементов. Например, внутри RoutePoint мне нужно инициализировать некоторые атрибуты значениями, которые содержат. Внутри RoutePointTakeOff мне нужно выполнить несколько алгоритмов. Проблема в том, что мне нужно выполнять разные функции в зависимости от раздела, в котором указатель.

Я новичок в программировании на C#, и я уверен, что существуют другие лучшие формы для доступа к этому типу данных.

Не могли бы вы помочь мне получить доступ к этим данным по типу?

«Сбой моей программы» - что именно происходит? Выдается исключение?

Sebastian Hofmann 25.06.2018 11:26

Я не могу заставить ваш XML анализировать! Вы уверены, что это действительно так?

Wheels73 25.06.2018 11:27

@ Wheels73 недействителен. Обратите внимание на незакрытые элементы.

Sebastian Hofmann 25.06.2018 11:28

@SebastianHofmann - Ах да ... Мне еще рано! Ваше здоровье!

Wheels73 25.06.2018 11:31

Вы уверены, что <RoutePoints> не имеет пространства имен (по умолчанию)? Что вам сообщает отладчик? Также вы не показали, как у вас появился i:

bommelding 25.06.2018 11:40

XML слишком велик, я использовал псевдокод для упрощения. Символ «+» указывает на то, что раздел может быть расширен (Подробнее).

JoseJimRin 25.06.2018 11:43
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
97
4

Ответы 4

Если вы используете FirstOrDefault вместо First, код работает так, как задумано, каждый элемент может быть обработан:

foreach (var routes in document.Descendants("RoutePoints"))
{
    foreach (var points in routes.Elements())
    {
        if (points.Attributes(i + "type").FirstOrDefault()?.Value == "RoutePoint")
        {
        }
        if (points.Attributes(i + "type").FirstOrDefault()?.Value == "RoutePointTakeOff")
        {
        }
        if (points.Attributes(i + "nil").FirstOrDefault()?.Value == "true")
        {
        }
        if (points.Attributes(i + "type").FirstOrDefault()?.Value == "RoutePointLanding")
        {
        }
    }
}

Обратите внимание на использование ? в качестве встроенной нулевой проверки, если соответствующий атрибут не найден.

Когда указатель находится в: <a: anyType z: Ref = "349" i: nil = "true" /> и проверьте FirstOrDefault () ?. Value == "RoutePointTakeOff", произойдет сбой программы, поскольку исключение NullReferenceException было необработанным.

JoseJimRin 25.06.2018 11:56

Нет, если у нас нет других файлов xml. Оператор ? не кидает.

Sebastian Hofmann 25.06.2018 12:15

Да не пользовался? оператор. Но не работает это для меня.

JoseJimRin 25.06.2018 14:02

Попробуйте следующее:

           XDocument doc = XDocument.Load(FILENAME);

            var results = doc.Descendants().Where(x => x.Name.LocalName == "anyType")
                .Select(x => new {
                    id = x.Attributes().Where(z => z.Name.LocalName == "Id").Select(z => (int)z).FirstOrDefault(),
                    _ref = x.Attributes().Where(z => z.Name.LocalName == "Ref").Select(z => (int)z).FirstOrDefault(),
                    type = x.Attributes().Where(z => z.Name.LocalName == "type").Select(z => (string)z).FirstOrDefault()
                }).ToList();

Это решение берет только атрибуты файла XML и помещает его в список, не так ли? Мне нужно взять элемент, информация, которую мне нужно обработать, находится внутри элементов. Например, внутри RoutePoint мне нужно инициализировать некоторые атрибуты значениями, которые содержат. Внутри RoutePointTakeOff мне нужно выполнить некоторые алгоритмы. Проблема в том, что мне нужно выполнять разные функции в зависимости от раздела, в котором указатель.

JoseJimRin 25.06.2018 12:09

Вы можете добавить свой код в мой. Используйте foreach (маршрут var в результатах) {}. Вам нужно будет проверить значение null. Значения будут id, _ref, type. Вы не включили в свой образец значение какого-либо элемента. Если есть элемент, добавьте value = (string) x как другую строку.

jdweng 25.06.2018 12:28

Попробуй это

public List<DataAttr> GetDataAttribute(XDocument xDocument)
    {
        var dataAttr = new List<DataAttr>();
        foreach (var route in xDocument.Descendants("RoutePoints"))
        {
            foreach (var point in route.Elements())
            {
                if (point.HasElements)
                {
                    dataAttr.AddRange(_getAttributeValues(point.Attributes()));
                }
            }
        }
        return dataAttr;
    }

    private static IEnumerable<DataAttr> _getAttributeValues(IEnumerable<XAttribute> attributes)
    {
        return attributes.Select(x => new DataAttr()
        {
            Name = x.Name.LocalName,
            Value = x.Value
        });
    }
public class DataAttr
{
    public string Name { get; set; }
    public string Value { get; set; }
}

после этого вы можете отсортировать группу данных по имени.

если вы используете этот код, вы не ограничены в названии атрибута. удачи.

Я отлаживал и наконец нашел ошибку ...

Я оценивал атрибут «тип», которого нет в строках 4-5. Это привело к ошибке. Более конкретно:

NullReferenceException was Unhandled

В конце концов, я использую нулевой элемент управления, и теперь он работает.

foreach ( var routes in document.Descendants("RoutePoints") ){
    foreach ( var points in routes.Elements() ) {
        if ( points.Attributes( i + "type").FirstOrDefault != null ){
             if ( points.Attributes(i+"type").First().Value == "RoutePoint") {
                //Processing..
             }
             if ( points.Attributes(i+"type").First().Value == "RoutePointTakeOff") {
                //Processing..
             }
             if ( points.Attributes(i+"type").First().Value == "RoutePointLanding") {
                //Processing..
             }
        } else {
             // Will execute this in rows 4-5    
        }
    }
}

Другие вопросы по теме