Чтение вложенного XML

У меня есть файл xml, и мне нужно сохранить значения в списке, чтобы использовать его позже. Файл xml содержит в основном ints and strings и выглядит так:

<AllThings>
      <Anythings>
        <Anything Step = "1" Name = "1">
          <Somethings>
            <Something Id = "10">
              <Things>
                <Thing Id = "11">abc</Thing>
                <Thing Id = "12">123</Thing>
              </Things>
            </Something>
            <Something Id = "20">
              <Things>
                <Thing Id = "21">cde</Thing>
                <Thing Id = "22">345</Thing>
              </Things>
            </Something>
            <Something Id = "30">
              <Things>
                <Thing Id = "31">efg</Thing>
                <Thing Id = "32">567</Thing>              
              </Things>
            </Something>
            <Something Id = "40">
              <Things>
                <Thing Id = "41">ghi</Thing>
                <Thing Id = "42">789</Thing>                
              </Things>
            </Something>
    </Somethings>
    </Anything>
    <Anything Step = "2" Name = "2">
          <Somethings>
            <Something Id = "10">
              <Things>
                <Thing Id = "11">aaa</Thing>
                <Thing Id = "12">111</Thing>
              </Things>
            </Something>
            <Something Id = "20">
              <Things>
                <Thing Id = "21">ccc</Thing>
                <Thing Id = "22">333</Thing>
              </Things>
            </Something>
            <Something Id = "30">
              <Things>
                <Thing Id = "31">eee</Thing>
                <Thing Id = "32">555</Thing>              
              </Things>
            </Something>
            <Something Id = "40">
              <Things>
                <Thing Id = "41">ggg</Thing>
                <Thing Id = "42">777</Thing>                
              </Things>
            </Something>
        </Somethings>
        </Anything>
    </Anythings>
</AllThings>

Каков наилучший способ получить значения из такого XML-файла и сохранить его в списках?

Я пытался с помощью using System.Xml; создать читалку и сделать reader.ReadToFollowing("Something") в сочетании с reader.GetAttribute("Id"), но этого недостаточно. В большинстве руководств xml выглядит так:

<Animal type = "cat">
  <Name>Bob</Name>
  <Age>8</Age>
</Animal>

И там это работает

Какие поля вы получаете для типа, имени и возраста?

Krishna Varma 21.11.2022 15:15

Следующее может быть полезно: stackoverflow.com/a/73640395/10024425 и stackoverflow.com/a/68232320/10024425

user09938 21.11.2022 16:05
Как настроить Tailwind CSS с React.js и Next.js?
Как настроить Tailwind CSS с React.js и Next.js?
Tailwind CSS - единственный фреймворк, который, как я убедился, масштабируется в больших командах. Он легко настраивается, адаптируется к любому...
LeetCode запись решения 2536. Увеличение подматриц на единицу
LeetCode запись решения 2536. Увеличение подматриц на единицу
Увеличение подматриц на единицу - LeetCode
Переключение светлых/темных тем
Переключение светлых/темных тем
В Microsoft Training - Guided Project - Build a simple website with web pages, CSS files and JavaScript files, мы объясняем, как CSS можно...
Отношения &quot;многие ко многим&quot; в Laravel с методами присоединения и отсоединения
Отношения &quot;многие ко многим&quot; в Laravel с методами присоединения и отсоединения
Отношения "многие ко многим" в Laravel могут быть немного сложными, но с помощью Eloquent ORM и его моделей мы можем сделать это с легкостью. В этой...
В PHP
В PHP
В большой кодовой базе с множеством различных компонентов классы, функции и константы могут иметь одинаковые имена. Это может привести к путанице и...
Карта дорог Беладжар PHP Laravel
Карта дорог Беладжар PHP Laravel
Laravel - это PHP-фреймворк, разработанный для облегчения разработки веб-приложений. Laravel предоставляет различные функции, упрощающие разработку...
0
2
60
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я думаю, вы пропустили повторение рекурсивно с помощью

.ChildNodes.OfType<XmlNode>().
Ответ принят как подходящий

Самый простой способ сделать это — использовать XmlSerialization. Для этого вам нужно будет создать структуру вложенного класса, соответствующую вашему xml. Существует множество утилит, которые сделают это автоматически (если вы ищете класс convert xml to c#), но я всегда чувствую, что полезно знать, как создать это самостоятельно.

Я всегда начинаю с внешней оболочки и продвигаюсь внутрь. Поэтому я сначала беру корневой элемент. AllThings имеет только один элемент AnyThings, поэтому этот класс легко создать (вам понадобится using System.Xml.Serialization;):

[XmlRoot]
public class AllThings
{

    [XmlElement]
    public Anythings Anythings { get; set; }
}

Далее мы смотрим на Anythings. Он содержит кучу элементов Anything, поэтому мы соответственно создаем следующий класс:

public class Anythings
{

    [XmlElement]
    public List<Anything> Anything { get; set; }
} 

Здесь следует отметить только одну вещь: связка Anything представлена ​​​​как List<Anything>.

Спускаемся снова вниз:

public class Anything
{

    [XmlElement]
    public Somethings Somethings { get; set; }

    [XmlAttribute]
    public int Step { get; set; }

    [XmlAttribute]
    public string Name { get; set; }

}

Здесь есть еще немного интересного: помимо XmlElement у нас есть два XmlAttributes. В вашем случае имя атрибута может легко быть int, учитывая значения в вашем xml, но, на мой взгляд, атрибут с именем Имя кричит, чтобы быть строкой!

И дальше вниз:

public class Somethings
{

    [XmlElement]
    public List<Something> Something { get; set; }
}

public class Something
{

    [XmlElement]
    public Things Things { get; set; }

    [XmlAttribute]
    public int Id { get; set; }
}


public class Things
{

    [XmlElement]
    public List<Thing> Thing { get; set; }
}

Все они строятся так же, как и раньше, оставляя только еще один класс:

public class Thing
{

    [XmlAttribute]
    public int Id { get; set; }

    [XmlText]
    public string Text { get; set; }
}

Это (наконец) добавляет что-то новое, базовый элемент XmlText, который представляет значение узла.

После настройки классов остается только вызвать встроенный десериализатор, например:

var xml = "<AllThings><Anythings><Anything Step=\"1\" Name=\"1\"><Somethings><Something Id=\"10\"><Things><Thing Id=\"11\">abc</Thing><Thing Id=\"12\">123</Thing></Things></Something><Something Id=\"20\"><Things><Thing Id=\"21\">cde</Thing><Thing Id=\"22\">345</Thing></Things></Something><Something Id=\"30\"><Things><Thing Id=\"31\">efg</Thing><Thing Id=\"32\">567</Thing></Things></Something><Something Id=\"40\"><Things><Thing Id=\"41\">ghi</Thing><Thing Id=\"42\">789</Thing></Things></Something></Somethings></Anything><Anything Step=\"2\" Name=\"2\"><Somethings><Something Id=\"10\"><Things><Thing Id=\"11\">aaa</Thing><Thing Id=\"12\">111</Thing></Things></Something><Something Id=\"20\"><Things><Thing Id=\"21\">ccc</Thing><Thing Id=\"22\">333</Thing></Things></Something><Something Id=\"30\"><Things><Thing Id=\"31\">eee</Thing><Thing Id=\"32\">555</Thing></Things></Something><Something Id=\"40\"><Things><Thing Id=\"41\">ggg</Thing><Thing Id=\"42\">777</Thing></Things></Something></Somethings></Anything></Anythings></AllThings>";

var serializer = new XmlSerializer(typeof(AllThings));
using (var reader = new StringReader(xml))
{ 
    var allThings = (AllThings)serializer.Deserialize(reader);
    //do something with allThings; 
}

Если вы используете отладчик для проверки allThings, вы обнаружите, что это объект c# со структурой, точно соответствующей вашему xml. Это означает, что вы можете получить доступ к его значениям с таким синтаксисом, как:

var test = allThings.Anythings.Anything[0].Somethings.Something[0].Things.Thing[0].Text;

Следующий код протестирован и работает

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace ConsoleApplication51
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {

            XmlReader reader = XmlReader.Create(FILENAME);
            XmlSerializer serializer = new XmlSerializer(typeof(AllThings));
            AllThings allthings = (AllThings)serializer.Deserialize(reader);
        }
    }
    public class AllThings
    {
        [XmlArray("Anythings")]
        [XmlArrayItem("Anything")]
        public List<AnyThing> anythings { get;set;}
    }
    public class AnyThing
    {
        [XmlAttribute()]
        public int Step { get;set;}
        [XmlAttribute()]
        public int Name { get; set; }

        [XmlArray("Somethings")]
        [XmlArrayItem("Something")]
        public List<Something> somethings { get; set; }
    }
    public class Something
    {
        [XmlAttribute()]
        public int Id { get; set; }

        [XmlArray("Things")]
        [XmlArrayItem("Thing")]
        public List<Thing> things { get;set;}
    }
    public class Thing
    {
        [XmlAttribute()]
        public int Id { get; set; }
        [XmlText]
        public string value { get; set; }
    }
 
}

В ваших списках есть два тега, такие как Somethings и SomeThing. Если в вашем xml нет двух тегов для массивов, используйте [XmlElement(tag)] вместо XmlArray и XmlArrayItem.

jdweng 22.11.2022 13:10

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