如何创建一个包含另外 2 个 XML 文件之间的值差异的 XML 文件

How can I create a XML file containing the difference in value between another 2 XML files

你好 C# 爱好者!

我正在尝试根据另外两个 xml 文件的元素减法创建一个 XML 文件(元素值的差异) 例如:

The Source Xml files

寻求输出:

Expected output

我做了一个快速的研究,发现有一个 XML 内容差异的库,但是 none 满足了这个 功能。

我知道这可以通过 System.xml class 解决,但我不知道如何开始。 任何帮助表示赞赏。

XML 文本示例:

<?xml version="1.0" encoding="utf-8"?>
<Report>
  <Project>
    <Name>P1</Name>
    <Runs>10</Runs>
    <Errors>5</Errors>
    <Successful>5</Successful>
  </Project>
.
. Multiple Projects exists here 
.
  <Project>
    <Name>P2</Name>
    <Runs>12</Runs>
    <Errors>3</Errors>
    <Successful>9</Successful>
  </Project>
  <Timestamp>
    <Year>2020</Year>
    <Month>6</Month>
    <Day>8</Day>
    <Hour>12</Hour>
  </Timestamp>
</Report>

尝试 xml linq。我假设您在输入和输出文件中都有相同的项目。如果不是,您将需要一个左外部连接。 :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication3
{
    class Program
    {
        const string INPUT_FILENAME_1 = @"c:\temp\test.xml";
        const string INPUT_FILENAME_2 = @"c:\temp\test1.xml";
        const string OUTPUT_FILENAME = @"c:\temp\test.xml2";
        static void Main(string[] args)
        {
            XDocument doc1 = XDocument.Load(INPUT_FILENAME_1);

            DateTime date1 = doc1.Descendants("Timestamp")
                .Select(x => new DateTime(
                    (int)x.Element("Year"),
                    (int)x.Element("Month"),
                    (int)x.Element("Day"),
                    (int)x.Element("Hour"),
                    0, 0)).FirstOrDefault();

            XDocument doc2 = XDocument.Load(INPUT_FILENAME_2);

            DateTime date2 = doc2.Descendants("Timestamp")
                .Select(x => new DateTime(
                    (int)x.Element("Year"),
                    (int)x.Element("Month"),
                    (int)x.Element("Day"),
                    (int)x.Element("Hour"),
                    0, 0)).FirstOrDefault();

            string ident = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Report></Report>";
            XDocument outputDoc = XDocument.Parse(ident);
            XElement outputReport = outputDoc.Root;
            XElement oldReport;
            XElement newReport;
            TimeSpan deltaTime; 

            if (date2 > date1)
            {
                newReport = doc2.Root;
                oldReport = doc1.Root;
                deltaTime = date2.Subtract(date1);
            }
            else
            {
                newReport = doc1.Root;
                oldReport = doc2.Root;
                deltaTime = date1.Subtract(date2);
            }

            var groups = (from n in newReport.Elements("Project")
                          join o in oldReport.Elements("Project")
                          on (string)n.Element("Name") equals (string)o.Element("Name")
                          select new { oldProj = o, newProj = n }
                          ).ToList();

            foreach (var group in groups)
            {
                XElement difference = new XElement("Project", new object[] {
                    new XElement("Name", (string)group.newProj.Element("Name")),
                    new XElement("Runs", (int)group.newProj.Element("Runs") - (int)group.oldProj.Element("Runs")),
                    new XElement("Errors", (int)group.newProj.Element("Errors") - (int)group.oldProj.Element("Errors")),
                    new XElement("Successful", (int)group.newProj.Element("Successful") - (int)group.oldProj.Element("Successful"))
                });
                outputReport.Add(difference);
            }

            XElement newTime = new  XElement("Timestamp", new object[] {
                new XElement("Year", 0),
                new XElement("Month", 0),
                new XElement("Day", deltaTime.Days),
                new XElement("Hour", deltaTime.Hours)
            });
            outputReport.Add(newTime);

            outputDoc.Save(OUTPUT_FILENAME);
        }
    }
}