我一直在研究各种方法来比较XML文件的目录,这样每个“实际构建”XML文件都有一个匹配的“模板构建”XML文件。这些模板将成为未来构建的实际配置文件,因此我需要返回当前正在运行的配置文件并检查数据的差异。这些差异将作为未来构建的客户端可更改配置包含在内。
我查看了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"
等等。
通过这种方式,我可以从Actual和Template文件中获取每一行,并根据它们是否具有相同的节点路径进行比较,然后比较文本。如果所有精确兄弟的文本不匹配,请输入字符串into 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();
}
答案 0 :(得分:1)
假设所有配置文件都是相同的(语法上)我会建议将它们读入一个对象并比较这些对象,这样你就有可能进行更细粒度的比较,例如字幕可能会被排除在比较之外。
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