Squeak.ru - шаблоны программирования

От вложенных объектов к XML-документу с использованием рекурсии

Мне известно о совете, предоставленном здесь

но, тем не менее, мне нужна помощь, чтобы понять, что в моем коде не так.

У меня есть список объектов, полученных из этого класса

public class Leaf
{
    public String key { get; set; }
    public String id { get; set; }
    public String value { get; set; }

    public List<Leaf> branch { get; set; } //children

    public Leaf()
    {
        branch = new List<Leaf>();
        key = "";
        id = "";
        value = "";
        parent_id_value = "";
    }

}

В основном у меня есть эти объекты:

List<Leaf> tree = new List<Leaf>();
 XElement xmloutput = new XElement("root");

Теперь я хотел бы пройтись по своему списку и его дочерним элементам, чтобы создать вложенную структуру XML, используя следующие правила:

  1. Когда у объекта Leaf нет дочерних элементов, процедура должна создать элемент <dictionaryitem/>.
  2. Когда у листа есть дочерние элементы, процедура должна создать <dictionarygroup></dictionarygroup>, который содержит дочерние элементы, которые являются либо элементом словаря, либо группой словарей, в зависимости от того, есть ли у них сами дочерние элементы или нет.
  3. И DictionaryItem, и DictionGroup имеют одинаковые атрибуты, производные от объекта Leaf.

Моя рекурсивная процедура выглядит следующим образом:

public static XElement CreateString(List<Leaf> tree, XElement xmloutput)
     {
         XElement xml = null;
         foreach(Leaf lf in tree)
         {
             if(lf.branch.Count > 0 && lf.branch[0].id!="")
             {

                 xml = new XElement("dictionarygroup",
                     new XAttribute("codeScheme", 1),
                     new XAttribute("codeValue", lf.id),
                     new XAttribute("codeMeaning", lf.value),
                     new XAttribute("codeSchemeVersion", "01"),
                     new XAttribute("isCancelled", "false"),
                     new XElement(CreateString(lf.branch, null))
                     );

             }
             else
             {
                 xml = new XElement("dictionaryItem",
                   new XAttribute("codeScheme", 1),
                   new XAttribute("codeValue", lf.id),
                   new XAttribute("codeMeaning", lf.value),
                   new XAttribute("codeSchemeVersion", "01"),
                   new XAttribute("isCancelled", "false")
                   );
             }

             if (xmloutput != null)
                 xmloutput.Add(xml);
             else
                 xmloutput = xml;

             xml = null;
         }

         return xmloutput;
     }

Он дает результат, но не ожидаемый; давайте рассмотрим эти данные в качестве примера:

List<Leaf> tree = new List<Leaf>();

        Leaf leaf1 = new Leaf();
        leaf1.key = "L1";
        leaf1.id = "257170";
        leaf1.value = "house";

        Leaf leaf2 = new Leaf();
        leaf2.key = "L1";
        leaf2.id = "44444";
        leaf2.value = "mouse";

        Leaf leaf1_1 = new Leaf();
        leaf1_1.key = "L2";
        leaf1_1.id = "323233";
        leaf1_1.value = "window";

        Leaf leaf1_2 = new Leaf();
        leaf1_2.key = "L2";
        leaf1_2.id = "666666";
        leaf1_2.value = "door";

        leaf1.branch.Add(leaf1_1);
        leaf1.branch.Add(leaf1_2);

        tree.Add(leaf1);
        tree.Add(leaf2);

Я ожидаю следующего результата:

<root>
<dictionarygroup codeScheme="1" codeValue="257170" codeMeaning="house" codeSchemeVersion="01" isCancelled="false">
    <dictionaryItem codeScheme="1" codeValue="323233" codeMeaning="window" codeSchemeVersion="01" isCancelled="false" />
    <dictionaryItem codeScheme="1" codeValue="666666" codeMeaning="door" codeSchemeVersion="01" isCancelled="false" />
</dictionarygroup>
<dictionaryItem codeScheme="1" codeValue="44444" codeMeaning="mouse" codeSchemeVersion="01" isCancelled="false" />

Instead I get this:

<root>
<dictionarygroup codeScheme="1" codeValue="257170" codeMeaning="house" codeSchemeVersion="01" isCancelled="false">
    <dictionaryItem codeScheme="1" codeValue="323233" codeMeaning="window" codeSchemeVersion="01" isCancelled="false">
        <dictionaryItem codeScheme="1" codeValue="666666" codeMeaning="door" codeSchemeVersion="01" isCancelled="false" />
    </dictionaryItem>
</dictionarygroup>
<dictionaryItem codeScheme="1" codeValue="44444" codeMeaning="mouse" codeSchemeVersion="01" isCancelled="false" />

So everytime there are children the first is used as a grouping tag that contains the other siblings, so it acts like a parent.

12.02.2018

  • сначала у вас ошибка в инициализации данных (лист 1 вместо листа1_1, лист2 вместо листа1_2). другая проблема, я узнаю сейчас 12.02.2018
  • Когда выполнение кода CreateString достигает leaf1_1, if (xmloutput != null) возвращает false и выполняется xmloutput = xml. И после него, когда CreateString выполняется для leaf1_2, условие if (xmloutput != null) возвращает true, а xmloutput содержит leaf1_1, и из-за этого вы получаете результат, который вам не нужен 12.02.2018
  • Таким образом, xmloutput.Add(xml) прикрепляет новый XElement как дочерний элемент XElement, который существует в xmloutput; Хорошо, есть идеи, как прикрепить новый XElement на уровне предыдущего XElement? 12.02.2018
  • Большое спасибо за ответы! 12.02.2018
  • Комбинация рекурсии + цикл все портит в методе CreateString 12.02.2018

Ответы:


1

Мне удалось исправить код с минимальными изменениями.

Часть инициализации данных:

List<Leaf> tree = new List<Leaf>();

Leaf leaf1 = new Leaf();
leaf1.key = "L1";
leaf1.id = "257170";
leaf1.value = "house";

Leaf leaf2 = new Leaf();
leaf2.key = "L1";
leaf2.id = "44444";
leaf2.value = "mouse";

Leaf leaf1_1 = new Leaf();
leaf1_1.key = "L2";
leaf1_1.id = "323233";
leaf1_1.value = "window";

Leaf leaf1_2 = new Leaf();
leaf1_2.key = "L2";
leaf1_2.id = "666666";
leaf1_2.value = "door";

leaf1.branch.Add(leaf1_1);
leaf1.branch.Add(leaf1_2);

tree.Add(leaf1);
tree.Add(leaf2);

//Create root element
XElement parentElement = new XElement("Root");

var result = CreateCorrectString(tree, parentElement);

Реализация CreateString:

public static XElement CreateCorrectString(List<Leaf> tree, XElement parent)
{
    XElement xml = null;
    foreach (Leaf lf in tree)
    {
        if (lf.branch.Count > 0 && lf.branch[0].id != "")
        {
            xml = new XElement("dictionarygroup",
                new XAttribute("codeScheme", 1),
                new XAttribute("codeValue", lf.id),
                new XAttribute("codeMeaning", lf.value),
                new XAttribute("codeSchemeVersion", "01"),
                new XAttribute("isCancelled", "false")
                );

            CreateCorrectString(lf.branch, xml);
        }
        else
        {
            xml = new XElement("dictionaryItem",
                new XAttribute("codeScheme", 1),
                new XAttribute("codeValue", lf.id),
                new XAttribute("codeMeaning", lf.value),
                new XAttribute("codeSchemeVersion", "01"),
                new XAttribute("isCancelled", "false")
                );

        }

        parent.Add(xml);

    }

    return parent;
}

P.S. Конечно, это не лучший алгоритм для указанной задачи, но я старался как можно меньше менять исходный код.

12.02.2018
  • Я понял, большое спасибо за совет, так как всегда очень полезно знать, что происходит не так. 12.02.2018
  • Тем временем я написал новую процедуру с использованием Xml.Serialization: ее довольно легко реализовать, она работает очень хорошо и совсем не доставляет мне головной боли!! 12.02.2018
  • Новые материалы

    Угловая структура архитектуры
    Обратите внимание, что эта статья устарела, я решил создать новую с лучшей структурой и с учетом автономных компонентов: https://medium.com/@marekpanti/angular-standalone-architecture-b645edd0d54a..

    «Данные, которые большинство людей используют для обучения своих моделей искусственного интеллекта, поставляются со встроенным…
    Первоначально опубликовано HalkTalks: https://hacktown.com.br/blog/blog/os-dados-que-a-maioria-das-pessoas-usa-para-treinar-seus-modelos-de-inteligencia-artificial- ja-vem-com-um-vies-embutido/..

    Сильный ИИ против слабого ИИ: различия парадигм искусственного интеллекта
    В последние годы изучению и развитию искусственного интеллекта (ИИ) уделяется большое внимание и прогресс. Сильный ИИ и Слабый ИИ — две основные парадигмы в области искусственного интеллекта...

    Правильный способ добавить Firebase в ваш проект React с помощью React Hooks
    React + Firebase - это мощная комбинация для быстрого и безопасного создания приложений, от проверки концепции до массового производства. Раньше (знаете, несколько месяцев назад) добавление..

    Создайте API с помощью Python FastAPI
    Создание API с помощью Python становится очень простым при использовании пакета FastAPI. После установки и импорта вы можете создать приложение FastAPI и указать несколько конечных точек. Каждой..

    Веселье с прокси-сервером JavaScript
    Прокси-серверы JavaScript — это чистый сахар, если вы хотите создать некоторую общую логику в своих приложениях, чтобы облегчить себе жизнь. Вот один пример: Связь клиент-сервер Мы..

    Получить бесплатный хостинг для разработчиков | Разместите свой сайт за несколько шагов 🔥
    Статические веб-сайты — это веб-страницы с фиксированным содержанием и его постоянным содержанием. Но теперь статические сайты также обрабатывают динамические данные с помощью API и запросов...