Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Преобразование XML дерева / 10 сообщений из 10, страница 1 из 1
15.08.2011, 13:22
    #37395716
sasha9001
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование XML дерева
Необходимо осуществить преобразование дерева 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
15.08.2011, 13:41
    #37395760
МСУ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование XML дерева
...
Рейтинг: 0 / 0
15.08.2011, 13:44
    #37395766
sasha9001
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование XML дерева
Необходимо осуществить преобразование дерева 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
15.08.2011, 15:39
    #37395987
bured
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование XML дерева
Элементарно, Ватсон, методом рекурсии.
Код: 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
15.08.2011, 15:40
    #37395989
bured
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование XML дерева
Упс, почистить забыл второпях...
...
Рейтинг: 0 / 0
15.08.2011, 15:46
    #37396005
bured
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование XML дерева
Рабинович, нашлись ложечки. Всё в порядке.

Код: 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
15.08.2011, 15:57
    #37396043
bured
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование XML дерева
оппа, только сейчас заметил parent_id. Ну извиняй, если что не так.
...
Рейтинг: 0 / 0
15.08.2011, 17:05
    #37396272
bured
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование XML дерева
Ну вот так работает, но не уверен, что оптимально.

Код: 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
15.08.2011, 17:56
    #37396392
bured
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование XML дерева
Если есть parent_id, level - избыточная информация. Этим ты меня и сбил с толку первоначально.
В общем, если оптимизируешь - выкладывай, не стесняйся.
...
Рейтинг: 0 / 0
15.08.2011, 18:34
    #37396458
sasha9001
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование XML дерева
В результате тоже додумался до рекурсии. Спасибо, что подтвердили направление движения.

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

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


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