c# - 复杂的 XML 差异

标签 c# xml linq

我一直在研究各种比较 XML 文件目录的方法,这样每个“实际构建”XML 文件都有一个匹配的“模板构建”XML 文件。这些模板将成为 future 构建的实际配置文件,因此我需要返回当前工作的配置文件并检查数据差异。这些差异将作为 future 构建的客户端可更改配置包含在内。

我查看了 XML Diff 和 Patch(GUI 和 VisStu 形式)并试图找出差异,但它左右返回异常并且永远无法创建 diffGram。似乎 XD&P 正在寻找不再存在或已以破坏它的方式更改的库元素。

现在,我是 XML 和 LINQ 的新手,但我知道这就是我的答案所在。我一直在考虑为每一行创建路径字符串,例如以下 xml 文件:

<configuration>
<title>#ClientOfficialName# Interactive Map</title>
<subtitle>Powered By Yada</subtitle>
<logo>assets/images/mainpageglobe.png</logo>
<style alpha="0.9">
    <colors>0xffffff,0x777777,0x555555,0x333333,0xffffff</colors>
    <font name="Verdana"/>
    <titlefont name="Verdana"/>
    <subtitlefont name="Verdana"/>
</style>

将创建如下字符串:

configuration/title/"#ClientOfficialName# Interactive Map"
configuration/subtitle/"Powered By Yada"
configuration/logo/"assets/iamges/mainpageglobe.png"
configuration/style/alpha/"0.9"
configuration/style/colors/"0xffffff,0x777777,0x555555,0x333333,0xffffff"

以此类推。

以这种方式,我可以从实际文件和模板文件中获取每一行,并根据“如果它们具有相同的节点路径,则比较文本。如果所有同胞的文本不匹配,则将字符串进入 differenceOutput.txt”。

到目前为止,这是我想出的最好的概念。如果有人可以帮助我实现这一目标(通过这种或任何其他方法),我将不胜感激。

我目前的目录系统没有问题,我只是不知道从哪里开始填充 xml 文件中的字符串容器:

static void Main(string[] args)
{
    //Set Up File Paths
    var actualBuildPath = @"C:\actual";
    var templateBuildPath = @"C:\template";

    //Output File Setups
    var missingFileList = new List<string>();
    var differenceList = new List<string>();

    //Iterate through Template Directory checking to see if the Current Build Directory 
    //has everything and finding differences if they exist
    foreach (var filePath in Directory.GetFiles(templateBuildPath, "*.xml", SearchOption.AllDirectories))
    {
        //Announce Current File
        Console.WriteLine("File: {0}  ", filePath);

        //Make Sure file Exists in current build
        if (File.Exists(filePath.Replace(templateBuildPath, actualBuildPath)))
        {
            //Fill in String Containers as prep for comparison
            var templateBuildFormattedXmlLines = PopulateStringContainerFromXML(filePath);
            var actualBuildFormattedXmlLines = PopulateStringContainerFromXML(filePath.Replace(templateBuildPath, actualBuildPath));

            //COMPARISON SECTION-------------------------------------------------------
            xmlFileCompare(templateBuildFormattedXmlLines, actualBuildFormattedXmlLines);
        }
        //Put missing file into missing file output file
        else
            missingFileList.Add("Missing: " + filePath.Replace(templateBuildPath, actualBuildPath));
    }

    //Create Output Folder and Output Files
    if (!Directory.Exists(actualBuildPath + @"\Outputs"))
        Directory.CreateDirectory(actualBuildPath + @"\Outputs");
    File.WriteAllLines(actualBuildPath + @"\Outputs\MissingFiles.txt", missingFileList);
    File.WriteAllLines(actualBuildPath + @"\Outputs\differenceList.txt", differenceList);

    //Wait to close console until user interacts
    Console.ReadLine();
}

最佳答案

假设所有配置文件(在语法上)都相同,我建议将它们读入一个对象并比较这些对象,这样您就有可能进行更细粒度的比较,例如,字幕可能会被排除在比较之外.

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

namespace XMLTest
{
    class Program
    {
        static void Main(string[] args)
        {
//You can use the XDocument.Load() Method to load a xml from a file path rather than a string
            string xml = "<configuration><title>#ClientOfficialName# Interactive Map</title><subtitle>Powered By Yada</subtitle><logo>assets/images/mainpageglobe.png</logo><style alpha=\"0.9\">    <colors>0xffffff,0x777777,0x555555,0x333333,0xffffff</colors>    <font name=\"Verdana\"/>    <titlefont name=\"Verdana\"/>    <subtitlefont name=\"Verdana\"/></style></configuration>";
            XDocument d = XDocument.Parse(xml);
            Configuration c = new Configuration();
            c.Title = d.Descendants().Where(x => x.Name == "title").FirstOrDefault().Value;
            c.SubTitle = d.Descendants().Where(x => x.Name == "subtitle").FirstOrDefault().Value;
            c.Logo = d.Descendants().Where(x => x.Name == "logo").FirstOrDefault().Value;

            Configuration.Style s = new Configuration.Style();
            s.Alpha = (from attr in d.Descendants().Attributes() select attr).Where(x => x.Name == "alpha").FirstOrDefault().Value;
            string tmp = d.Descendants().Where(x => x.Name == "colors").FirstOrDefault().Value;
            foreach (string str in tmp.Split(','))
            {
                s.Colors.Add(Convert.ToInt32(str, 16));
            }
            s.FontName = (from attr in d.Descendants().Where(x=>x.Name =="font").Attributes() select attr).Where(x => x.Name == "name").FirstOrDefault().Value;
            s.TitleFontName = (from attr in d.Descendants().Where(x => x.Name == "titlefont").Attributes() select attr).Where(x => x.Name == "name").FirstOrDefault().Value;
            s.SubtitleFontName = (from attr in d.Descendants().Where(x => x.Name == "subtitlefont").Attributes() select attr).Where(x => x.Name == "name").FirstOrDefault().Value;

            c.MyStyle = s;

            Console.WriteLine(c.ToString());
            Console.ReadKey();
        }
    }
    public class Configuration : IComparable
    {

        public string Title;
        public string SubTitle;
        public string Logo;
        public Style MyStyle;

        public override string ToString()
        {
            return string.Format("Configuration : Title: {0}, Subtitle {1}, Logo {2}, Style: {3}",Title,SubTitle,Logo,MyStyle.ToString());
        }
        public class Style
        {
            public string Alpha;
            public List<int> Colors = new List<int>();
            public string FontName;
            public string TitleFontName;
            public string SubtitleFontName;

            public override string ToString()
            {
                string s = "Alpha :" +Alpha;
                s+= ", Colors: ";
                foreach(int i in Colors){
                    s += string.Format("{0:x},",i);
                }
                s += " FontName :" + FontName;
                s += " TitleFontName :" + TitleFontName;
                s += " SubTitleFontName :" + SubtitleFontName;
                return s;
            }
        }

        public int CompareTo(object obj)
        {
            if ((obj as Configuration) == null)
            {
                throw new ArgumentException("Not instance of configuration");
            }
            //Very simple comparison, ranks by the title in the comparison object, here you could compare all the other values e.g Subtitle , logo and such to test if two instances are Equal
            return String.Compare(this.Title, ((Configuration)obj).Title, true);
        }
    }
}

有关实现比较的更完整概述,请参阅:https://msdn.microsoft.com/en-us/library/system.icomparable.compareto%28v=vs.110%29.aspx

关于c# - 复杂的 XML 差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34274641/

相关文章:

c# - 停止 Visual Studio 在 C# 中对我导入的接口(interface)成员进行排序?

ios - 可以通过 "Postman software"获取 XML 数据,但无法通过 SWIFT 获取数据

XML targetNamespace 和元素的非限定声明

c# - 在 C# 中的多列上按结构列表分组

c# - Visual Studio (C#) 'Hot code replace'

c# - 字符串格式 - 如何更改负号位置

java - 从java中的soap响应创建一个json

C# Interface IEnumerable Any() 没有指定泛型类型

C# 获取不同的最大值

c# - 为什么 Mutex 在处置时不被释放?