簡體   English   中英

合並xml文檔

[英]Merging of xml documents

我遇到的有關合並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>

文檔的內容相似,但可以具有任意數量的子節點。 我也想消除重復。 我認為重復是具有相同屬性的元素(基於屬性名稱和值)。 有誰見過這個實現的工作示例? 我可以設想如何使用一些循環和一些遞歸來編寫它,但對我來說,這似乎不是實現我想要的最佳方式:)

歡呼並提前致謝!

* 編輯 *

既然共識是循環和遞歸是必須的,那么最優雅和有效的方法是什么呢? 我想這個問題的另一個基本問題是在迭代時比較節點的最佳方法是什么?

最終,對此問題的任何解決方案都將歸結為循環和/或遞歸。 你說的是基本集理論,而linq可能對提煉過程很有用,但最終會迭代兩個集合並合並結果。

我寫了一個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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM