我有兩個XML文件,我需要結合並保留最新更改的OriginalXML和UpdatesXML。我的用戶從本質上獲得了一個OriginalXML的副本,進行編輯,然後將更新提交給Web服務。我只需要使用UpdatesXML中較新的節點來更新OriginalXML。C#僅結合XML最新節點
我可以通過在UpdatesXML節點重複,做搜索的OriginalXML的進行匹配,檢查時間戳,如果更新爲新的替換:(像)
var OriginalXML = XDocument.Load("Original.xml");
var UpdatesXML = XDocument.Load("Updates.xml");
foreach (XElement WigitNode in UpdatesXML.Descendants("Wigit"))
{
//Find the corresponding OriginalXML node based on the Wigit/Subnode1/Id attribute
//Replace Original/Wigit with Updates/Wigit if Updates/Wigit/Editstamp/Timestamp attribute is later in Updates than Original
}
這整個事情對我來說似乎相當笨拙,特別是如果Updates.xml有很多節點的話。我的用例可能每次幾十個,所以它可能不是問題,但似乎效率低下。有沒有簡單的XPath或xslt轉換或者更快或更高效的轉換?
我的XML看起來是這樣的: Original.xml:
<?xml version="1.0" encoding="utf-8"?>
<Root>
<Wigit>
<EditStamp UserId="timmy" Timestamp="2013-09-13T20:22:00" />
<Subnode1 Id="A" />
</Wigit>
<Wigit>
<EditStamp UserId="phil" Timestamp="2013-09-13T21:51:00" />
<Subnode1 Id="B" />
</Wigit>
<Wigit>
<EditStamp UserId="biff" Timestamp="2013-10-13T21:51:00" />
<Subnode1 Id="C" />
</Wigit>
</Root>
Updates.xml:
<?xml version="1.0" encoding="utf-8"?>
<Root>
<Wigit>
<EditStamp UserId="frank" Timestamp="2013-10-13T22:00:00" />
<Subnode1 Id="A" />
</Wigit>
</Root>
和所需的輸出是:
<?xml version="1.0" encoding="utf-8"?>
<Root>
<Wigit>
<EditStamp UserId="frank" Timestamp="2013-10-13T22:00:00" />
<Subnode1 Id="A" />
</Wigit>
<Wigit>
<EditStamp UserId="phil" Timestamp="2013-09-13T21:51:00" />
<Subnode1 Id="B" />
</Wigit>
<Wigit>
<EditStamp UserId="biff" Timestamp="2013-10-13T21:51:00" />
<Subnode1 Id="C" />
</Wigit>
</Root>
更新:10 -15-2013
我做了一些使用下面Abhijeet Patel的代碼擺弄以及與此想出了:
var query = from o in docOriginal.Element("Root").Elements("Wigit")
from u in docUpdate.Element("Root").Elements("Wigit")
let x = docUpdate.Element("Root")
.Elements("Wigit")
.SingleOrDefault(e => (e.Element("Subnode1").Attribute("id").Value == o.Element("Subnode1").Attribute("id").Value &&
DateTime.Parse(e.Element("EditStamp").Attribute("Timestamp").Value).Ticks > DateTime.Parse(o.Element("EditStamp").Attribute("Timestamp").Value).Ticks)) ?? o
select x;
XDocument merged = new XDocument(new XElement("Root", query));
return merged;
這給了正確的結果,除了每個節點被複制:
<Root>
<Wigit>
<EditStamp UserId="frank" Timestamp="2013-10-13T22:00:00" />
<Subnode1 Id="SomeNewThing" />
</Wigit>
<Wigit>
<EditStamp UserId="frank" Timestamp="2013-10-13T22:00:00" />
<Subnode1 Id="SomeNewThing" />
</Wigit>
<Wigit>
<EditStamp UserId="phil" Timestamp="2013-09-13T21:51:00" />
<Subnode1 Id="B" />
</Wigit>
<Wigit>
<EditStamp UserId="phil" Timestamp="2013-09-13T21:51:00" />
<Subnode1 Id="B" />
</Wigit>
<Wigit>
<EditStamp UserId="biff" Timestamp="2013-10-13T21:51:00" />
<Subnode1 Id="C" />
</Wigit>
<Wigit>
<EditStamp UserId="biff" Timestamp="2013-10-13T21:51:00" />
<Subnode1 Id="C" />
</Wigit>
</Root>
任何提示就如何不重複結果?
更新2013年10月16日:
我得到重複結果的原因是因爲我用的是更新的文檔有兩個節點。代碼需要一次處理多個更改,只更新具有更大時間戳的節點。
string update = @"<?xml version='1.0' encoding='utf-8'?>
<Root>
<Wigit id='A'>
<EditStamp UserId='frank' Timestamp='2013-10-13T22:00:00' />
<Subnode1 Id='SomeNewThing' />
</Wigit>
<Wigit id='B'>
<EditStamp UserId='yomamma' Timestamp='2013-09-10T21:51:00' />
<Subnode1 Id='B' />
</Wigit>
</Root>";
這真的非常接近我所需要的一個小問題是,查詢的結果中有自己的節點每節點(和赫然簡單!)。 ' ... ' –
nickvans
'在調試過程中對我的部分進行監督。我更新了答案。基本上,Linq查詢中的選擇需要做'選擇x'現在試試:-) –
你是我的英雄!十分感謝你的幫助! – nickvans