Слияние XML-документов - PullRequest
       4

Слияние XML-документов

12 голосов
/ 11 октября 2011

Все решения, с которыми я сталкивался относительно слияния XML-документов, не достигают того, чего я желаю.Позвольте мне объяснить:

XML-документ 1:

<?xml version="1.0" encoding="utf-8" ?>
<a>
    <b title="Original Section">
        <b title="Original Child Section"></b>
        <b title="Original Child Section 2"></b>
    </b>
</a>

XML-документ 2:

<?xml version="1.0" encoding="utf-8" ?>
<a>
    <b title="New Section">
        <b title="New Child Section"></b>
    </b>
    <b title="Original Section">
        <b title="Original Child Section">
            <b title="New Child For Old Section"></b>
        </b>
    </b>    
</a>

В окончательный документ, подобный этому:

<?xml version="1.0" encoding="utf-8" ?>
<a>
    <b title="Original Section">
        <b title="Original Child Section">
            <b title="New Child For Old Section"></b>
        </b>
        <b title="Original Child Section 2"></b>
    </b>    
    <b title="New Section">
        <b title="New Child Section"></b>
    </b>
</a>

Документы похожи по содержанию, но могут иметь произвольное количество дочерних узлов.Я также хотел бы устранить дубликаты.Я считаю, что дубликаты являются элементами с одинаковыми атрибутами (в зависимости от имени и значения атрибута).Кто-нибудь видел рабочий пример этой реализации?Я могу представить, как бы я написал это, используя несколько циклов и немного рекурсии, но для меня это просто не лучший способ достичь того, чего я хочу:)

Приветствия и заранее спасибо!

* РЕДАКТИРОВАТЬ *

Поскольку существует общее мнение, что циклы и рекурсия являются обязательнымиКаков будет самый элегантный и эффективный способ сделать это?Я полагаю, что еще один фундаментальный вопрос к этой проблеме: каков наилучший способ сравнения узлов во время итерации?

Ответы [ 2 ]

1 голос
/ 12 октября 2011

Я бы написал IEqualityComparer, который указывает, когда два узла являются «совпадающими», т.е. устанавливает правило сопоставления заголовков.

class XElementComparer : IEqualityComparer<XElement>
{
    public bool Equals(XElement x, XElement y)
    {
        var xTitle = x.Attribute("title");
        var yTitle = y.Attribute("title");

        if (xTitle == null || yTitle == null) return false;

        return xTitle.Value == yTitle.Value;
    }

    public int GetHashCode(XElement obj)
    {
        return base.GetHashCode();
    }
}

А затем напишите рекурсивный метод для обхода вашего XML, объединяя узлы, которые соответствуют в соответствии с компаратором.

private XElement Merge(XElement node1, XElement node2)
{
    // trivial cases
    if (node1 == null) return node2;
    if (node2 == null) return node1;

    var elements1 = node1.Elements();
    var elements2 = node2.Elements();

    // create a merged root
    var result = new XElement(node1.Name, node1.Attribute("title")); 

    var comparer = new XElementComparer();
    var mergedNodes = elements1.Union(elements2, comparer).ToList();

    // for the union of the elements, insert their merge values
    foreach (var title in mergedNodes)
    {
        var child1 = elements1.SingleOrDefault(e => comparer.Equals(e, title));
        var child2 = elements2.SingleOrDefault(e => comparer.Equals(e, title));

        result.Add(Merge(child1, child2));
    }

    return result;
}
1 голос
/ 12 октября 2011

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

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