我是从我原来的职位重新措辞:我有两个XML文件,并将它们与每个给定的一年。例如,18/19和17/18。他们遵循相同的结构,下面是从这些文件中的一个小样本。我要的是,在C#中,比较这些文件在给定的名称,族名称时,NI号码和出生日期是相同的所有记录,但学习者参考数是不同的。我需要能够进行比较,然后把只有这些记录到一个数据表,然后我就可以把他们变成一个电子表格(电子表格位我可以做)。目前,我有以下作为起始块,但我还是很坚持。
首先,我有我的导入按钮操作,其中:
private void Btn_Import_Click(object sender, RoutedEventArgs e)
{
ILRChecks.ILRReport.CrossYear();}
那么这个去看看它的最终推动文件到我的位置类:
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ILRValidation;
using InfExcelExtension;
namespace ILRChecks
{
internal static partial class ILRReport
{
internal static void CrossYear()
{
DataSet ds_CrossYearChecks =
ILRValidation.Validation.CrossYearChecks(Global.fileNames);
string output = Path.Combine(Global.foldername, "ULIN_Issues" +
".xlsx");
ds_CrossYearChecks.ToWorkBook(output);
}
}
}
这是我卡上的位,这是生产寻找差异:
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ILRValidation
{
public static partial class Validation
{
public static DataSet CrossYearChecks(DataSet ds_CrossYearChecks)
{
return CrossYearChecks(ds_CrossYearChecks);
}
public static DataSet CrossYearChecks(string[] xmlPath)
{
DataSet ds_xmlCrossYear = new DataSet();
return CrossYearChecks(ds_xmlCrossYear);
}
}
}
XML:
<Learner>
<LearnRefNumber></LearnRefNumber>
<ULN></ULN>
<FamilyName></FamilyName>
<GivenNames></GivenNames>
<DateOfBirth></DateOfBirth>
<Ethnicity></Ethnicity>
<Sex></Sex>
<LLDDHealthProb></LLDDHealthProb>
<NINumber></NINumber>
<PriorAttain></PriorAttain>
<MathGrade></MathGrade>
<EngGrade></EngGrade>
<PostcodePrior></PostcodePrior>
<Postcode></Postcode>
<AddLine1></AddLine1>
<AddLine3></AddLine3>
<Email></Email>
那么,你可以递归遍历XML两种文件,并记下所有遇到的变化。喜欢的东西应该是有帮助:
static string AppendPrefix(string oldPrefix, string addition) =>
oldPrefix == "" ? addition : $"{oldPrefix}.{addition}";
static void CompareElements(string prefix, XElement d1, XElement d2)
{
// 1. compare names
var newPrefix = AppendPrefix(prefix, d1.Name.ToString());
if (d1.Name != d2.Name)
{
Console.WriteLine(
$"Name mismatch: {newPrefix} != {AppendPrefix(prefix, d2.Name.ToString())}");
return;
}
// 2. compare attributes
var attrs = d1.Attributes().OrderBy(a => a.Name);
var unpairedAttributes = new HashSet<XAttribute>(d2.Attributes());
foreach (var attr in attrs)
{
var otherAttr = d2.Attributes(attr.Name).SingleOrDefault();
if (otherAttr == null)
{
Console.WriteLine($"No new attr: {newPrefix}/{attr.Name}");
continue;
}
unpairedAttributes.Remove(otherAttr);
if (attr.Value != otherAttr.Value)
Console.WriteLine(
$"Attr value mismatch: {newPrefix}/{attr.Name}: {attr.Value} != {otherAttr.Value}");
}
foreach (var attr in unpairedAttributes)
Console.WriteLine($"No old attr: {newPrefix}/{attr.Name}");
// 3. compare subelements
var leftNodes = d1.Nodes().ToList();
var rightNodes = d2.Nodes().ToList();
var smallerCount = Math.Min(leftNodes.Count, rightNodes.Count);
for (int i = 0; i < smallerCount; i++)
CompareNodes(newPrefix, i, leftNodes[i], rightNodes[i]);
if (leftNodes.Count > smallerCount)
Console.WriteLine($"Extra {leftNodes.Count - smallerCount} nodes at old file");
if (rightNodes.Count > smallerCount)
Console.WriteLine($"Extra {rightNodes.Count - smallerCount} nodes at new file");
}
static void CompareNodes(string prefix, int index, XNode n1, XNode n2)
{
if (n1.NodeType != n2.NodeType)
{
Console.WriteLine($"Node type mismatch: {prefix}/[{index}]");
return;
}
switch (n1.NodeType)
{
case XmlNodeType.Element:
CompareElements(prefix, (XElement)n1, (XElement)n2);
break;
case XmlNodeType.Text:
CompareText(prefix, index, (XText)n1, (XText)n2);
break;
}
}
static void CompareText(string prefix, int index, XText t1, XText t2)
{
if (t1.Value != t2.Value)
Console.WriteLine($"Text mismatch at {prefix}[{index}]");
}
用法:
XDocument d1 = <get document #1 from somewhere>,
d2 = <get document #2 from somewhere>;
CompareNodes("", 0, d1.Root, d2.Root);
显然,不是写作来安慰你应该写在相应的电子表格。
请注意,我忽略了属性重新排序,但没有子节点重新排序(这似乎是正确的)。
在我看来,您无法从XML提取你想要的值,是否正确?
当别人在评论中所提到的,不知道你的XML布局其不可能给你的情况下的具体例子。如果您编辑的问题,包括您的XML的例子,我们可以帮助更多。
下面是如何提取XML值一些通用的例子:
private static bool CheckXmlDocument(string xmlPathCheck)
{
// if you have multiple files from which you need to extract values, pass in an array or List<string> and loop over it, fetching the values
// XmlDocument will allow you to edit the document as well as read it
// there's another option to use XPathDocument and XPathNavigator but it's read-only
var doc = new XmlDocument();
// this can throw various exceptions so might want to add some handling
doc.Load(xmlPathCheck);
// getting the elements, you have some options depending on the layout of the document
// if the nodes you want are identified by 'id' use this:
var nameElement = doc.GetElementById("name");
// if the nodes you want are identified by 'tag', use this:
var nameNodeList = doc.GetElementsByTagName("name");
// if you know the xpath to the specific node you want, use this:
var selectNameNode = doc.SelectSingleNode("the/xpath/to/the/node");
// if there are several nodes that have the same xpaths, use this:
var selectNameList = doc.SelectNodes("the/xpath/that/may/match/many/nodes");
// getting the value depends on the if you have an XmlNode, XmlElement or XmlNodeList
// if you have a single XmlElement or XmlNode you can get the value one of these ways depending on the layout of your document:
var name = nameElement.InnerText;
name = nameElement.InnerXml;
// if you have an XmlNodeList, you'll have to iterate through the nodes to find the one you want, like this:
foreach (var node in nameNodeList)
{
// here use some condition that will determine if its the element/node you want or not (depends on your xml layout)
if (node is XmlNode n)
{
name = n.InnerText;
}
}
// do that for all the values you want to compare, then compare them
return CheckValues(/*the values to compare*/);
}