C# 仅组合 XML 最新节点

本文关键字:最新 节点 XML 组合 | 更新日期: 2023-09-27 18:35:15

我有两个XML文件,OriginalXML和UpdatesXML,我需要合并并仅保留最新的更改。我的用户基本上获得了OriginalXML的副本,进行编辑,然后将更新提交到Web服务。我只需要使用UpdatesXML中较新的节点更新OriginalXML。

我可以遍历 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
}

这整个事情对我来说似乎相当笨拙,特别是如果更新.xml有很多节点。我的用例可能一次有几十个,所以这可能不是问题,但似乎效率低下。是否有一个简单的 XPath 或 xslt 转换或更快或更高效的东西?

我的 XML 如下所示:原文.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>

更新.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>

关于如何不重复结果的任何提示?

更新 10-16-2013:

我得到重复结果的原因是因为我使用的更新文档有两个节点。代码需要一次处理多个更改,仅更新具有更大时间戳的节点。

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>";

C# 仅组合 XML 最新节点

试试这个:

            string original = @"<?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>";
        string update = @"<?xml version='1.0' encoding='utf-8'?>
                        <Root>
                            <Wigit>
                                <EditStamp UserId='frank' Timestamp='2010-10-13T22:00:00' />
                                <Subnode1 Id='A' />
                            </Wigit>
                            <Wigit id='B'>
                                <EditStamp UserId='yomamma' Timestamp='2013-09-09T21:51:00' />
                                <Subnode1 Id='B' />
                           </Wigit>
                    </Root>";
        XDocument docOriginal = XDocument.Parse(original);
        XDocument docUpdate = XDocument.Parse(update);
        var query = from o in docOriginal.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) > DateTime.Parse(o.Element("EditStamp").Attribute("Timestamp").Value))
                                     ) ?? o
                    select x;
        XDocument merged = new XDocument(new XElement("Root", query));
        Console.WriteLine(merged.ToString());