linq: группировка, сортировка и удаление дублирующихся узлов из XML - PullRequest
0 голосов
/ 18 сентября 2018

У меня есть меню xml вроде этого:

<root>
    <item name="submenu" href="">
        <item name="delete post" href="example.com/delete" />
        **<item name="delete post" href="" />**
        **<item name="add post" href="" />**
        <item name="add post" href="example.com/add" />
        **<item name="add post" href="" />**
        <item name="do not remove" href="" />        
    </item>
    <item name="list post" href="example.com/list" />
    **<item name="list post" href="" />**
    <item name="remove only one of these" href="" />
    **<item name="remove only one of these" href="" />**
</root>

Мне нужно удалить дубликаты и найти решение здесь: эффективное удаление дублирующихся элементов xml в c #

Моя проблема в том, что если заполнено href, я хочу сохранить эту точную запись - поэтому мне нужно отсортировать их после группировки, но перед удалением записи.

Поэтому мне нужно удалить записи, отмеченные **, ноне могу найти способ заставить OrderBy(string.IsNullOrWhiteSpace) работать с GroupBy.

Любая помощь приветствуется.

Ответы [ 2 ]

0 голосов
/ 18 сентября 2018

Это непростая проблема, связанная с рекурсивной природой xml для работы в любых условиях.Вам необходимо использовать рекурсивный метод, подобный приведенному ниже.

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

namespace ConsoleApplication67
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);
            XElement root = doc.Root;
            RemoveRecursive(root);
        }

        static void RemoveRecursive(XElement element)
        {
            var groups = element.Elements()
                .GroupBy(x => new { tagname = x.Name.LocalName, itemname = (string)x.Attribute("name") })
                .Select(x => x.Select(y => new { element = y, index = (string)y.Attribute("href") == "" ? 0 : 1 })).ToList();

            foreach(var group in groups)
            {
                var orderGroup = group.OrderByDescending(x => x.index).ToList();
                for (int i = orderGroup.Count() - 1; i > 0; i--)
                {
                    orderGroup[i].element.Remove();
                }
            }
            foreach(XElement child in element.Elements())
            {
                if (child.HasElements) RemoveRecursive(child);
            }
        }
    }
}
0 голосов
/ 18 сентября 2018

Это то, что вы ищете?

public class Item
{
    public string Name { get; set; }
    public string Href { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var data = new List<Item>
        {
            new Item { Name="1", Href="" },
            new Item { Name="1", Href="b" },
            new Item { Name="2", Href="c" },
            new Item { Name="2", Href="" },
            new Item { Name="2", Href="" },
        };

        var results = data.OrderBy(d => d.Name).ThenByDescending(d => d.Href).GroupBy(d => d.Name).Select(g => g.First());

        foreach (var result in results)
        {
            Console.WriteLine(result.Name + ", " + result.Href);
        }

        Console.ReadLine();
    }
}

Результаты:

1, b

2, c

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...