Создайте дерево узлов xml из результирующего набора, но объединив повторяющиеся атрибуты с помощью linq или выражений

#c# #asp.net #xml #linq

#c# #asp.net #xml #linq

Вопрос:

Привет, у меня есть набор данных в следующем формате:

 NodeID | NodeName | NodeAttribute1 | NodeAttribute2
   1   |    n1    |       1        |      null
   2   |    n2    |       1        |      null
   3   |    n3    |       1        |        1
   4   |    n4    |       2        |        2
   5   |    n5    |       2        |        3
   6   |    n6    |       2        |        4
  

В основном, атрибуты определяют положение узла в виртуальном дереве. Я хочу, чтобы результат выглядел следующим образом:

 <NodeTree>
    <ParentNodeType1 NodeAttribute1 = 1> 
        <node name="n1" nodeID=1>
        <node name="n2" nodeID=2>
        <ParentNodeType2 NodeAttribute2 = 1>
            <node name = "n3" nodeID = 3>
        </ParentNodeType2>
    </ParentNodeType1>
    <ParentNodeType1 NodeAttribute1 = 2> 
        <ParentNodeType2 NodeAttribute2 = 3>
            <node name = "n4" nodeID=4>
        </ParentNodeType2>
        <ParentNodeType2 NodeAttribute2 = 4>
            <node name = "n5" nodeID=5>
            <node name = "n6" nodeID=6>
        </ParentNodeType2>
    </ParentNodeType1>
</NodeTree>
  

Итак, n1 и n2 находятся в parent1, но n3 на один уровень глубже, потому что второй атрибут не равен null. У кого-нибудь есть какие-либо мысли о том, как это можно сделать с помощью linq или чего-то подобного?

Комментарии:

1. Спасибо Эдуардо за очистку моей таблицы .. Новичок на этом сайте..

2. Кстати, я думаю, что Эдуардо также перепутал данные. Исходная таблица намного лучше соответствовала фрагменту XML… Ирония

Ответ №1:

Извините, я пытался разобраться в этом, но у меня не получилось.

Ваши данные, похоже, описаны не очень хорошо (каковы атрибуты? Почему вы не хотите, чтобы иерархия отображалась в XML? Какими должны быть ParentNodeType1 / 2? NodeAttribute2, похоже, является идентификатором родительского узла, однако в XML-узлах n5 и n6 оба находятся под <ParentNodeType2 NodeAttribute2 = 4> я был недостаточно умен, чтобы обнаружить логику там 🙂

Тем не менее, в попытке помочь вам, вот что, я думаю, было бы полезно, и вы можете просто адаптировать это к вашим «требованиям», не заставляя меня об этом знать (подмигивание)

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

namespace X 
{ 
    static class Y 
    {
        public static int Main(string[] args)
        {
            var data = new Record[] {
                new Record(1, "n1", 1, null),
                    new Record(2, "n2", 1, null),
                    new Record(3, "n3", 1, 1),
                    new Record(4, "n4", 2, 2),
                    new Record(5, "n5", 2, 3),
                    new Record(6, "n6", 2, 4),
            };

            Func<Record, XElement> subtree;
            subtree = node => new XElement("node", 
                    new XAttribute("name", node.NodeName),
                    new XAttribute("nodeID", node.NodeID),
                    new XAttribute("NodeAttribute1", node.NodeAttribute1),
                    data.ChildrenOf(node.NodeID).Select(subtree));

            XElement xml = new XElement("NodeTree",
                    data.Where(root => root.NodeAttribute2 == null)
                    .Select(subtree));

            Console.WriteLine(xml);
            return 0;
        }

        struct Record
        {
            public readonly int NodeID;
            public readonly string NodeName;
            public readonly int  NodeAttribute1; //level?
            public readonly int? NodeAttribute2; //parent

            internal Record(int id, string name, int at1, int? at2) 
            {
                NodeID = id;
                NodeName = name;
                NodeAttribute1 = at1;
                NodeAttribute2 = at2;
            }
        }

        private static IEnumerable<Record> ChildrenOf(this IEnumerable<Record> data, int? parentId)
        {
            return data.Where(child => child.NodeAttribute2 == parentId);
        }
    }
}
  

О, на всякий случай, вот результат

 <NodeTree>
  <node name="n1" nodeID="1" NodeAttribute1="1">
    <node name="n3" nodeID="3" NodeAttribute1="1">
      <node name="n5" nodeID="5" NodeAttribute1="2" />
    </node>
  </node>
  <node name="n2" nodeID="2" NodeAttribute1="1">
    <node name="n4" nodeID="4" NodeAttribute1="2">
      <node name="n6" nodeID="6" NodeAttribute1="2" />
    </node>
  </node>
</NodeTree>
  

Комментарии:

1. Я прошу прощения за то, что недостаточно ясно выразился. Я просто вызвал в воображении этот пример, чтобы помочь понять, какой код потребуется для выполнения такого рода задач. В основном я изучаю различные идеи для хранения иерархических данных. Основная идея, лежащая в основе этого, заключается в том, что каждая строка будет содержать достаточно информации, чтобы вы знали, где она находится в дереве. Каждый столбец атрибутов представляет уровень в дереве. Тем не менее, спасибо за ваш ответ..

2. Хорошо, для поискового запроса, я думаю, мой пример должен дать вам надежные идеи. (Кроме того, я настроился на напыщенную речь после того, как понял ваши намерения и обнаружил, что сообщение было неправильно отредактировано кем-то другим). Приветствия

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