powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Преобразование XML дерева
10 сообщений из 10, страница 1 из 1
Преобразование XML дерева
    #37395716
sasha9001
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Необходимо осуществить преобразование дерева XML:
Т.е. имеется XML документ вида
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
<types>
   <type parent_id="0" id="1" level="1">value  1 </type>
   <type parent_id="0" id="1" level="1">value  1 </type>
   <type parent_id="0" id="1" level="1">value  1 </type>
   <type parent_id="0" id="1" level="1">value  1 </type>
   <type parent_id="0" id="1" level="1">value  1 </type>
   <type parent_id="0" id="1" level="1">value  1 </type>
   <type parent_id="0" id="1" level="1">value  1 </type>
   <type parent_id="0" id="1" level="1">value  1 </type>
   <type parent_id="0" id="1" level="1">value  1 </type>
   <type parent_id="0" id="1" level="1">value  1 </type>
</types>
Необходимо получить XML такого вида:
Код: plaintext
1.

Пока получилось что-то типа нижепоказанного, но код самому не нравится - очень много проходов по XML. Чувствую, что все можно сделать намного эффективнее, но как - пока допереть не могу. Может, кто поможет бедному студенту.
Код: plaintext
1.
...
Рейтинг: 0 / 0
Преобразование XML дерева
    #37395760
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Преобразование XML дерева
    #37395766
sasha9001
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Необходимо осуществить преобразование дерева XML:
Т.е. имеется XML документ вида
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
<types>
   <type parent_id="0" id="1" level="1">value  1 </type>
   <type parent_id="1" id="2" level="2">value  2 </type>
   <type parent_id="2" id="3" level="3">value  3 </type>
   <type parent_id="3" id="4" level="4">value  4 </type>
   <type parent_id="3" id="5" level="4">value  5 </type>
   <type parent_id="2" id="6" level="3">value  6 </type>
   <type parent_id="6" id="7" level="4">value  7 </type>
   <type parent_id="6" id="8" level="4">value  8 </type>
   <type parent_id="1" id="9" level="2">value  9 </type>
   <type parent_id="9" id="10" level="3">value  10 </type>
   <type parent_id="10" id="11" level="4">value  11 </type>
   <type parent_id="10" id="12" level="4">value  12 </type>
   <type parent_id="10" id="13" level="4">value  13 </type>
   <type parent_id="10" id="14" level="4">value  14 </type>
   <type parent_id="1" id="15" level="2">value  15 </type>
   <type parent_id="15" id="16" level="3">value  16 </type>
   <type parent_id="16" id="17" level="4">value  17 </type>
   ...................................
</types>

Необходимо получить XML такого вида:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
<types>
   <type name="value 1">
        <subtype1 name="value 2">
               <subtype2 name="value 3">
                      <subtype3 name="value 4"/>
                      <subtype3 name="value 5"/>
               </subtype2>
               <subtype2 name="value 6">
                      <subtype3 name="value 7"/>
                      <subtype3 name="value 8"/>
               </subtype2>
        </subtype1>
        <subtype1 name="value 9">
               <subtype2 name="value 10">
                      <subtype3 name="value 11"/>
                      <subtype3 name="value 12"/>
                      <subtype3 name="value 13"/>
                      <subtype3 name="value 14"/>
               </subtype2>
        </subtype1>
        <subtype1 name="value 15">
               <subtype2 name="value 10">
                      <subtype3 name="value 11"/>
               </subtype2>
        </subtype1>
  </type>
  ....................
  <type name="value nnn">
  .................
</types>

Пока получилось что-то типа нижепоказанного, но код самому не нравится - очень много проходов по XML. Чувствую, что все можно сделать намного эффективнее, но как - пока допереть не могу. Может, кто поможет бедному студенту.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
public static ConvertXML ( string inputPath, string outputPath)
{
   XDocument xDoc = XDocument.Load ( inputPath );
   XElement root = xDoc.Root;
   var grps = from el in root.Elelments("type")
                     group by new
                     {
                          cat1 = el.Attribute("level").Value;
                          cat2 = el.Attribute("parent_id").Value;
                     } into g
                     select g;

   XDocument nDoc = new XDocument();
   nDoc.Add(new XElement("types"));
   
  bool flag = false;

   foreach (var i in grps)
   {
       foreach (var j in i)
       {
               if (flag)
               {
                      var el = from s in nDoc.Root.Descendants()
                                 where s.Attribute("id").Value == j.Attribute("parent_id").Value
                                 select s;
                      el.First().Add(j);
               }
               else
                     nDoc.Root.Add(j);
       }
       flag = true;
   }

   ....... и т.д. - тут уже чисто техническая трансформация.

}
...
Рейтинг: 0 / 0
Преобразование XML дерева
    #37395987
Фотография bured
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Элементарно, Ватсон, методом рекурсии.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
public static class Utils
{
    public static void GetChilds(this XElement parent)
    {
       var childs = parent.ElementsAfterSelf().TakeWhile(el => Convert.ToInt32(el.Attribute("level").Value) > Convert.ToInt32(parent.Attribute("level").Value));       
       parent.Value = "";
       parent.Name = "type" + parent.Attribute("level").Value.ToString();
        foreach (var ch in childs)
       {
           ch.GetChilds();           
           parent.Add(ch);
       }
    }
}

 protected void Page_Load(object sender, EventArgs e)
{
        XDocument doc = XDocument.Load(MapPath(@"App_Data/in.xml"));
        var fst = doc.Element("types").Elements("type").Where(el => el.Attribute("level").Value == "1").First();
        fst.GetChilds();
        fst.Save(MapPath(@"App_Data/out.xml"));
}

in

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
<?xml version="1.0" encoding="utf-8" ?>
  <types>
    <type parent_id="0" id="1" level="1">value  1 </type>
    <type parent_id="1" id="2" level="2">value  2 </type>
    <type parent_id="2" id="3" level="3">value  3 </type>
    <type parent_id="3" id="4" level="4">value  4 </type>
    <type parent_id="3" id="5" level="4">value  5 </type>
    <type parent_id="2" id="6" level="3">value  6 </type>
    <type parent_id="6" id="7" level="4">value  7 </type>
    <type parent_id="6" id="8" level="4">value  8 </type>
    <type parent_id="1" id="9" level="2">value  9 </type>
    <type parent_id="9" id="10" level="3">value  10 </type>
    <type parent_id="10" id="11" level="4">value  11 </type>
    <type parent_id="10" id="12" level="4">value  12 </type>
    <type parent_id="10" id="13" level="4">value  13 </type>
    <type parent_id="10" id="14" level="4">value  14 </type>
    <type parent_id="1" id="15" level="2">value  15 </type>
    <type parent_id="15" id="16" level="3">value  16 </type>
    <type parent_id="16" id="17" level="4">value  17 </type>    
  </types>

out

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
<?xml version="1.0" encoding="utf-8"?>
<type1 parent_id="0" id="1" level="1">
  <type2 parent_id="1" id="2" level="2">
    <type3 parent_id="2" id="3" level="3">
      <type4 parent_id="3" id="4" level="4"></type4>
      <type4 parent_id="3" id="5" level="4"></type4>
    </type3>
    <type4 parent_id="3" id="4" level="4"></type4>
    <type4 parent_id="3" id="5" level="4"></type4>
    <type3 parent_id="2" id="6" level="3">
      <type4 parent_id="6" id="7" level="4"></type4>
      <type4 parent_id="6" id="8" level="4"></type4>
    </type3>
    <type4 parent_id="6" id="7" level="4"></type4>
    <type4 parent_id="6" id="8" level="4"></type4>
  </type2>
  <type3 parent_id="2" id="3" level="3">
    <type4 parent_id="3" id="4" level="4"></type4>
    <type4 parent_id="3" id="5" level="4"></type4>
  </type3>
  <type4 parent_id="3" id="4" level="4"></type4>
  <type4 parent_id="3" id="5" level="4"></type4>
  <type3 parent_id="2" id="6" level="3">
    <type4 parent_id="6" id="7" level="4"></type4>
    <type4 parent_id="6" id="8" level="4"></type4>
  </type3>
  <type4 parent_id="6" id="7" level="4"></type4>
  <type4 parent_id="6" id="8" level="4"></type4>
  <type2 parent_id="1" id="9" level="2">
    <type3 parent_id="9" id="10" level="3">
      <type4 parent_id="10" id="11" level="4"></type4>
      <type4 parent_id="10" id="12" level="4"></type4>
      <type4 parent_id="10" id="13" level="4"></type4>
      <type4 parent_id="10" id="14" level="4"></type4>
    </type3>
    <type4 parent_id="10" id="11" level="4"></type4>
    <type4 parent_id="10" id="12" level="4"></type4>
    <type4 parent_id="10" id="13" level="4"></type4>
    <type4 parent_id="10" id="14" level="4"></type4>
  </type2>
  <type3 parent_id="9" id="10" level="3">
    <type4 parent_id="10" id="11" level="4"></type4>
    <type4 parent_id="10" id="12" level="4"></type4>
    <type4 parent_id="10" id="13" level="4"></type4>
    <type4 parent_id="10" id="14" level="4"></type4>
  </type3>
  <type4 parent_id="10" id="11" level="4"></type4>
  <type4 parent_id="10" id="12" level="4"></type4>
  <type4 parent_id="10" id="13" level="4"></type4>
  <type4 parent_id="10" id="14" level="4"></type4>
  <type2 parent_id="1" id="15" level="2">
    <type3 parent_id="15" id="16" level="3">
      <type4 parent_id="16" id="17" level="4"></type4>
    </type3>
    <type4 parent_id="16" id="17" level="4"></type4>
  </type2>
  <type3 parent_id="15" id="16" level="3">
    <type4 parent_id="16" id="17" level="4"></type4>
  </type3>
  <type4 parent_id="16" id="17" level="4"></type4>
</type1>

Эти свои value сам впихни куда надо.
...
Рейтинг: 0 / 0
Преобразование XML дерева
    #37395989
Фотография bured
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Упс, почистить забыл второпях...
...
Рейтинг: 0 / 0
Преобразование XML дерева
    #37396005
Фотография bured
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Рабинович, нашлись ложечки. Всё в порядке.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
public static void GetChilds(this XElement parent)
    {
       var childs = parent.ElementsAfterSelf()
           .TakeWhile(el => Convert.ToInt32(el.Attribute("level").Value) > Convert.ToInt32(parent.Attribute("level").Value))
           .Where(el => Convert.ToInt32(el.Attribute("level").Value) == Convert.ToInt32(parent.Attribute("level").Value)+1);       
       parent.Value = "";
       parent.Name = "type" + parent.Attribute("level").Value.ToString();
        foreach (var ch in childs)
       {
           ch.GetChilds();           
           parent.Add(ch);
       }
    }

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
<?xml version="1.0" encoding="utf-8"?>
<type1 parent_id="0" id="1" level="1">
  <type2 parent_id="1" id="2" level="2">
    <type3 parent_id="2" id="3" level="3">
      <type4 parent_id="3" id="4" level="4"></type4>
      <type4 parent_id="3" id="5" level="4"></type4>
    </type3>
    <type3 parent_id="2" id="6" level="3">
      <type4 parent_id="6" id="7" level="4"></type4>
      <type4 parent_id="6" id="8" level="4"></type4>
    </type3>
  </type2>
  <type2 parent_id="1" id="9" level="2">
    <type3 parent_id="9" id="10" level="3">
      <type4 parent_id="10" id="11" level="4"></type4>
      <type4 parent_id="10" id="12" level="4"></type4>
      <type4 parent_id="10" id="13" level="4"></type4>
      <type4 parent_id="10" id="14" level="4"></type4>
    </type3>
  </type2>
  <type2 parent_id="1" id="15" level="2">
    <type3 parent_id="15" id="16" level="3">
      <type4 parent_id="16" id="17" level="4"></type4>
    </type3>
  </type2>
</type1>
...
Рейтинг: 0 / 0
Преобразование XML дерева
    #37396043
Фотография bured
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
оппа, только сейчас заметил parent_id. Ну извиняй, если что не так.
...
Рейтинг: 0 / 0
Преобразование XML дерева
    #37396272
Фотография bured
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну вот так работает, но не уверен, что оптимально.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
public static void GetChilds(this XElement parent, XDocument doc)
    {
        var childs = doc.Descendants("type")
           .Where(el => el.Attribute("parent_id").Value == parent.Attribute("id").Value ); 
      
       parent.Name = "type" + parent.Attribute("level").Value.ToString();
        foreach (var ch in childs)
       {
           ch.GetChilds(doc);           
           parent.Add(ch);
       }
    }
////
XDocument doc = XDocument.Load(MapPath(@"App_Data/in.xml"));        
        var root = doc.Element("types").Elements("type").Where(el => el.Attribute("level").Value == "1").First();
        root.GetChilds(doc);        
        root.Save(MapPath(@"App_Data/out.xml"));
...
Рейтинг: 0 / 0
Преобразование XML дерева
    #37396392
Фотография bured
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если есть parent_id, level - избыточная информация. Этим ты меня и сбил с толку первоначально.
В общем, если оптимизируешь - выкладывай, не стесняйся.
...
Рейтинг: 0 / 0
Преобразование XML дерева
    #37396458
sasha9001
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В результате тоже додумался до рекурсии. Спасибо, что подтвердили направление движения.

level, кстати, инфа совсем нелишняя. Если известен максимальный уровень вложенности, то позволяет отсечь лишние запросы. Но это уже бантики.

Смущает только слишком много запросов. Вот бы как-нибудь одним запросом обойтись. Мечта...
...
Рейтинг: 0 / 0
10 сообщений из 10, страница 1 из 1
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Преобразование XML дерева
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]