powered by simpleCommunicator - 2.0.54     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / C#, слияние двух XML
6 сообщений из 6, страница 1 из 1
C#, слияние двух XML
    #38605534
Grunch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте!
Есть задача объеденить две xml с одинаковой структурой
1:
Код: xml
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.
<?xml version="1.0" ?>
<menu>
<game name="123" index="" images="">
<description>123</description>
<cloneof></cloneof>
<crc></crc>
<manufacturer>J-Wing</manufacturer>
<year>1996</year>
<genre></genre>
</game>
<game name="123" index="" images="">
<description>123</description>
<cloneof></cloneof>
<crc></crc>
<manufacturer>J-Wing</manufacturer>
<year>1996</year>
<genre></genre>
</game>
<game name="1qeee" index="" images="">
<description>qweqwe</description>
<cloneof></cloneof>
<crc></crc>
<manufacturer>J-Wing</manufacturer>
<year>1996</year>
<genre></genre>
</game>
</menu>


2:
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
<?xml version="1.0" ?>
<menu>
<game name="123" index="" images="">
<description>123</description>
<cloneof></cloneof>
<crc></crc>
<manufacturer>J-Wing</manufacturer>
<year>1996</year>
<genre></genre>
</game>
<game name="456" index="" images="">
<description>456</description>
<cloneof></cloneof>
<crc></crc>
<manufacturer>J-Wing</manufacturer>
<year>1996</year>
<genre></genre>
</game>
</menu>


При этом необходимо оставить только уникальные узлы. Уникальность определяется по атрибуту name

Сделал так:
Код: c#
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 class GameComparer : IEqualityComparer<XElement>
    {
        public bool Equals(XElement x, XElement y)
        {
            return x.Attribute("name").Value == y.Attribute("name").Value;
        }

        public int GetHashCode(XElement obj)
        {
            return (obj == null ? 0 : obj.GetHashCode());
        }
    }

    class XmlMerge
    {
        public static XmlDocument Merge(string xml1, string xml2)
        {
            XElement root1 = XElement.Parse(xml1);
            XElement root2 = XElement.Parse(xml2);

            StringBuilder s = new StringBuilder();

            IEnumerable<XElement> games1 = from a in root1.Elements("game") select a;
            IEnumerable<XElement> games2 = from b in root2.Elements("game") select b;
            IEnumerable<XElement> games = from g in games1.Union(games2).Distinct() select g;
            s.Append("<?xml version=\"1.0\"?>");
            s.Append("<menu>");
            foreach (XElement el in games)
            {
                s.Append(el);
            }
            s.Append("</menu>");
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(s.ToString());
            return doc;
        }
    }


В итоговом XML все равно присутствуют дубликаты, при отладке вообще не заходит в метод GameComparer.Equal
Что может быть не так, в каком направлении копать?
...
Рейтинг: 0 / 0
C#, слияние двух XML
    #38605539
Grunch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: c#
1.
IEnumerable<XElement> games = from g in games1.Union(games2).Distinct() select g;


читать как
Код: c#
1.
IEnumerable<XElement> games = from g in games1.Union(games2).Distinct(new GameComparer()) select g;
...
Рейтинг: 0 / 0
C#, слияние двух XML
    #38605829
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Grunch,

в Equal не заходит, потому что хэшкоды у элементов разные.

Нужно переписать метод GetHashCode:
Код: c#
1.
2.
3.
4.
public int GetHashCode(XElement obj)
{
    return obj.Attribute("name").Value.GetHashCode();
}



Сам код я бы тоже переписал. Зачем используется StringBuilder? Почему используются два разных API - XmlDocument и XElement?
Код: c#
1.
2.
3.
4.
5.
6.
7.
var games1 = root1.Elements("game");
var games2 = root2.Elements("game");

var games = games1.Union(games2, new GameComparer());

var doc = new XDocument(new XElement("menu"));
doc.Root.Add(games);
...
Рейтинг: 0 / 0
C#, слияние двух XML
    #38605837
Grunch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо! Заработало.
Код корявый, потому что только начал изучать C#, еще не все возможности языка знаю. За подсказки спасибо!
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
C#, слияние двух XML
    #38968905
DMF84
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.
Понимаю, тема давно для вас не актуальна, но я сталкнулся с подобной же задачей. К сожалению, ваш пример в моём случае почему-то не работает. Может подскажите где я не прав.

VS выдаёт ошибку:
Код: c#
1.
"System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement>" не содержит определения для "Union" и не был найден метод расширения "Union", принимающий тип "System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement>" в качестве первого аргумента (возможно, пропущена директива using или ссылка на сборку)
...
Рейтинг: 0 / 0
C#, слияние двух XML
    #38968973
Grunch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DMF84,

Смотрите версию .Net. Метод Enumerable.Union появился, вроде, только в .Net 3.5
...
Рейтинг: 0 / 0
6 сообщений из 6, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / C#, слияние двух XML
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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