2012-09-10 86 views
1

我需要将2个xml文件“合并”在一起,但要考虑在两者中出现的元素和合并属性,这些属性在每个属性中都不相同。下面是我的意思的例子:使用LINQ合并2个Xml文件

输入:XML1

<?xml version="1.0"?> 
<Style Width="1024" Height="768"> 
    <BaseStyle Width="1024" Height="768" BackgroundPath="./Images/BackgroundAAA.png"/> 
    <Styles> 
     <LabelStyle ID="Label1" Font="Tahoma" Bold="false" /> <!-- exists in both --> 
     <LabelStyle ID="Label2" Font="Tahoma" Bold="false" /> <!-- exists in both --> 
     <LabelStyle ID="Label3" Font="Tahoma" Bold="false" /> <!-- unique --> 
    </Styles> 
</Style> 

输入:XML2

<?xml version="1.0"?> 
<Style Width="1024" Height="768"> 
    <BaseStyle Width="1024" Height="768" BackgroundPath="./Images/BackgroundBBB.png"/> 
    <Styles> 
     <LabelStyle ID="Label1" Font="Arial" Bold="true" /> <!-- exists in both --> 
     <LabelStyle ID="Label2" Font="Arial" /> <!-- exists in both --> 
     <LabelStyle ID="Label4" Font="Arial" Bold="false" /> <!-- unique --> 
    </Styles> 
</Style> 

,我需要得到以下的输出: -

结果:Xml3

<?xml version="1.0"?> 
<Style Width="1024" Height="768"> 
    <BaseStyle Width="1024" Height="768" BackgroundPath="./Images/BackgroundBBB.png"/> <!-- has overwritten Xml1 --> 
    <Styles> 
     <LabelStyle ID="Label1" Font="Arial" Bold="true" /> <!-- has merged Xml1 & Xml2 with Xml2 taking precedence --> 
     <LabelStyle ID="Label2" Font="Arial" Bold="false" /> <!-- has merged Xml1 & Xml2 with Xml2 taking precedence (note Bold attribute is present) --> 
     <LabelStyle ID="Label3" Font="Tahoma" Bold="false" /> <!-- unique --> 
     <LabelStyle ID="Label4" Font="Arial" Bold="false" /> <!-- unique --> 
    </Styles> 
</Style> 

您会注意到,从上面可以看出,任何唯一的东西都会被合并,任何常见的东西(使用ID作为关键字)都会使用Xml2值进行更新。

我一直在阅读一些关于如何使用LINQ合并2个xml文件的很多好问题,但他们都没有真正满足我的要求。他们似乎都在谈论拿A和B并以A + B结束。

有没有一种简单的方法来使用LINQ来做到这一点?

在此先感谢!

+0

你见过这样的:** HTTP://stackoverflow.com/questions/4937875/merging -two-xml-files-linq ** –

回答

2

例如:

class Program { 
    static void Main(string[] args) { 
     StringReader sr = new StringReader("<?xml version=\"1.0\"?><Style Width=\"1024\" Height=\"768\"><BaseStyle Width=\"1024\" Height=\"768\" BackgroundPath=\"./Images/BackgroundBBB.png\"/><Styles><LabelStyle ID=\"Label1\" Font=\"Arial\" Bold=\"true\" /> <!-- exists in both --><LabelStyle ID=\"Label2\" Font=\"Arial\" /> <!-- exists in both --><LabelStyle ID=\"Label3\" Font=\"Arial\" Bold=\"false\" /> <!-- unique --></Styles></Style>"); 
     XDocument xdoc1 = XDocument.Load(sr); 
     sr.Close(); 
     sr = new StringReader("<?xml version=\"1.0\"?><Style Width=\"1024\" Height=\"768\"><BaseStyle Width=\"1024\" Height=\"768\" BackgroundPath=\"./Images/BackgroundBBB.png\"/><Styles><LabelStyle ID=\"Label1\" Font=\"Arial\" Bold=\"true\" /> <!-- exists in both --><LabelStyle ID=\"Label2\" Font=\"Arial\" /> <!-- exists in both --><LabelStyle ID=\"Label4\" Font=\"Arial\" Bold=\"false\" /> <!-- unique --></Styles></Style>"); 
     XDocument xdoc2 = XDocument.Load(sr); 
     sr.Close(); 

     sr = new StringReader("<?xml version=\"1.0\"?><Style Width=\"1024\" Height=\"768\"><BaseStyle Width=\"1024\" Height=\"768\" BackgroundPath=\"./Images/BackgroundBBB.png\"/><Styles></Styles></Style>"); 
     XDocument xDocDest = XDocument.Load(sr); 
     sr.Close(); 
     XElement xeDest = xDocDest.Root.Descendants("Styles").Single(); 

     XElement[] x2s = (from x in xdoc2.Root.Descendants("LabelStyle") orderby x.Attribute("ID").Value select x).ToArray() ; 

     Int32 iCurrentX2 = 0; 
     XElement xeCurrentX2 = (x2s.Count() > 1) ? x2s[0] : null; 
     foreach (XElement x1 in from x in xdoc1.Root.Descendants("LabelStyle") orderby x.Attribute("ID").Value select x) { 
      if (xeCurrentX2 == null || String.Compare(x1.Attribute("ID").Value, xeCurrentX2.Attribute("ID").Value) < 0) { 
       xeDest.Add(x1); 
      } else { 
       while (iCurrentX2 < x2s.Count() && String.Compare(x1.Attribute("ID").Value, xeCurrentX2.Attribute("ID").Value) >= 0) { 
        xeDest.Add(xeCurrentX2); 
        xeCurrentX2 = (++iCurrentX2 < x2s.Count()) ? x2s[iCurrentX2] : null; 
       } 
      } 
     } 
     while (iCurrentX2 < x2s.Count()) { 
      xeDest.Add(x2s[iCurrentX2++]); 
     } 

     Console.WriteLine(xDocDest.ToString()); 
    } 
} 

,这是不完全确定下来,但我认为结构是这里

+0

谢谢@ tschmit007 - 真的很接近:)! 只是几个问题: - 1.输出做合并的元素,但没有拿起Xml1和Xml2有Label2,字体应该更新为Arial(来自Tahoma)的事实。我认为你在这里的状况是'它不在那里,加上它。'这几乎适合我! 2.在Xml1:BaseStyle上,属性BackgroundPath是“BackgroundAAA.png”,而在Xml2上属于BackgroundBBB.png。是否有可能“合并这些,所以最终结果是按照Xml3? 非常感谢您的回复 - 非常感谢! – Slippy

+0

这里,我认为你可以从实际的代码处理 – tschmit007