如何使用 C# 代码消除重复的 XML 节点
How to eliminate duplicate XML nodes using C# code
我有一个架构 XML 文件,其中包含 Table、列和外键的节点,如下所示。
<Table schema="Reports_vN" name="pstpyr" caption="PR Payroll Posting">
<Column name="recnum" alias="Record Number" isprimarykey="1" />
<Column name="pstnum" alias="Posting Number" />
</Table>
<Table schema="Reports_vN" name="payrec" caption="PR Payroll Record">
<Column name="recnum" alias="Record Number" isprimarykey="1" />
<Column name="empnum" alias="Employee" />
<Column name="strprd" alias="Period Start" />
<ForeignKey pkSchema="Reports_vN" pkTable="payrec" fkSchema="Reports_vN" fkTable="tmcdln" name="Record Number">
<ForeignKeyCol pkCol="recnum" fkCol="recnum" />
</ForeignKey>
<ForeignKey pkSchema="Reports_vN" pkTable="payrec" fkSchema="Reports_vN" fkTable="jobcst" name="Payroll Number">
<ForeignKeyCol pkCol="recnum" fkCol="payrec" />
</ForeignKey>
<ForeignKey pkSchema="Reports_vN" pkTable="payrec" fkSchema="Reports_vN" fkTable="jobcst" name="Payroll Number">
<ForeignKeyCol pkCol="recnum" fkCol="payrec" />
</ForeignKey>
</Table>
就像上面观察到的那样,它包含重复元素(最后两个外键)。我是 LINQ 的新手。有人可以分享一个示例,我可以使用它从 XML 文件中删除这个重复的元素。
首先,您的 XML
格式不正确。您有多个根节点,这是非法的。 <Table>
个节点应该放在一个根节点下。
那么,您还没有完全定义什么是 duplicate 节点。它是否仅通过节点名称进行复制?还是节点子节点和属性也必须相同?
1。仅按节点(元素)名称重复
这很简单。您通过该名称获取所有元素,然后执行 Skip(1)
到 跳过 第一个,然后删除其余的。
XDocument xDoc = XDocument.Load("data.xml");
xDoc.Root.Descendants("ForeignKey").Skip(1).Remove();
现在 XML
看起来像这样:
<MyRoot>
<Table schema="Reports_vN" name="pstpyr" caption="PR Payroll Posting">
<Column name="recnum" alias="Record Number" isprimarykey="1" />
<Column name="pstnum" alias="Posting Number" />
</Table>
<Table schema="Reports_vN" name="payrec" caption="PR Payroll Record">
<Column name="recnum" alias="Record Number" isprimarykey="1" />
<Column name="empnum" alias="Employee" />
<Column name="strprd" alias="Period Start" />
<ForeignKey pkSchema="Reports_vN" pkTable="payrec" fkSchema="Reports_vN" fkTable="tmcdln" name="Record Number">
<ForeignKeyCol pkCol="recnum" fkCol="recnum" />
</ForeignKey>
</Table>
</MyRoot>
2。彻底检查包括子元素和属性
我说,你最好的选择是使用Deserialization
。首先,您需要创建一组符合您的 XML
格式的 类。根据您提供的 XML
,它看起来像这样。请注意,我添加了一个 _root 节点,名为 MyRoot
.
[XmlRoot("MyRoot")]
public class MyRoot
{
[XmlElement("Table")]
public List<Table> Tables { get; set; }
}
public class Table
{
[XmlAttribute("schema")]
public string Schema { get; set; }
[XmlAttribute("name")]
public string Name { get; set; }
[XmlAttribute("caption")]
public string Caption { get; set; }
[XmlElement("Column")]
public List<Column> Columns { get; set; }
[XmlElement("ForeignKey")]
public List<ForeignKey> ForeignKeys { get; set; }
}
public class Column
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlAttribute("alias")]
public string Alias { get; set; }
[XmlAttribute("isprimarykey")]
public string IsPrimaryKey { get; set; }
}
public class ForeignKey
{
[XmlAttribute("pkSchema")]
public string PkSchema { get; set; }
[XmlAttribute("pkTable")]
public string PkTable { get; set; }
[XmlAttribute("fkSchema")]
public string FkSchema { get; set; }
[XmlAttribute("fkTable")]
public string FkTable { get; set; }
[XmlAttribute("name")]
public string Name { get; set; }
[XmlElement("ForeignKeyCol")]
public ForeignKeyCol ForeignKeyCol { get; set; }
}
public class ForeignKeyCol
{
[XmlAttribute("pkCol")]
public string PkCol { get; set; }
[XmlAttribute("fkCol")]
public string FkCol { get; set; }
}
现在,您可以使用以下方法反序列化您的XML
。
public static T DeserializeXMLFileToObject<T>(string XmlFilename)
{
T returnObject = default(T);
if (string.IsNullOrEmpty(XmlFilename)) return default(T);
try
{
StreamReader xmlStream = new StreamReader(XmlFilename);
XmlSerializer serializer = new XmlSerializer(typeof(T));
returnObject = (T)serializer.Deserialize(xmlStream);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return returnObject;
}
这样称呼它:
MyRoot xml = DeserializeXMLFileToObject<MyRoot>("data.xml");
现在需要使用简单的 C#
技术来查找和删除重复项。最简单的方法是写一个 Comparer
这样你就可以轻松地比较多个对象。
我有一个架构 XML 文件,其中包含 Table、列和外键的节点,如下所示。
<Table schema="Reports_vN" name="pstpyr" caption="PR Payroll Posting">
<Column name="recnum" alias="Record Number" isprimarykey="1" />
<Column name="pstnum" alias="Posting Number" />
</Table>
<Table schema="Reports_vN" name="payrec" caption="PR Payroll Record">
<Column name="recnum" alias="Record Number" isprimarykey="1" />
<Column name="empnum" alias="Employee" />
<Column name="strprd" alias="Period Start" />
<ForeignKey pkSchema="Reports_vN" pkTable="payrec" fkSchema="Reports_vN" fkTable="tmcdln" name="Record Number">
<ForeignKeyCol pkCol="recnum" fkCol="recnum" />
</ForeignKey>
<ForeignKey pkSchema="Reports_vN" pkTable="payrec" fkSchema="Reports_vN" fkTable="jobcst" name="Payroll Number">
<ForeignKeyCol pkCol="recnum" fkCol="payrec" />
</ForeignKey>
<ForeignKey pkSchema="Reports_vN" pkTable="payrec" fkSchema="Reports_vN" fkTable="jobcst" name="Payroll Number">
<ForeignKeyCol pkCol="recnum" fkCol="payrec" />
</ForeignKey>
</Table>
就像上面观察到的那样,它包含重复元素(最后两个外键)。我是 LINQ 的新手。有人可以分享一个示例,我可以使用它从 XML 文件中删除这个重复的元素。
首先,您的 XML
格式不正确。您有多个根节点,这是非法的。 <Table>
个节点应该放在一个根节点下。
那么,您还没有完全定义什么是 duplicate 节点。它是否仅通过节点名称进行复制?还是节点子节点和属性也必须相同?
1。仅按节点(元素)名称重复
这很简单。您通过该名称获取所有元素,然后执行 Skip(1)
到 跳过 第一个,然后删除其余的。
XDocument xDoc = XDocument.Load("data.xml");
xDoc.Root.Descendants("ForeignKey").Skip(1).Remove();
现在 XML
看起来像这样:
<MyRoot>
<Table schema="Reports_vN" name="pstpyr" caption="PR Payroll Posting">
<Column name="recnum" alias="Record Number" isprimarykey="1" />
<Column name="pstnum" alias="Posting Number" />
</Table>
<Table schema="Reports_vN" name="payrec" caption="PR Payroll Record">
<Column name="recnum" alias="Record Number" isprimarykey="1" />
<Column name="empnum" alias="Employee" />
<Column name="strprd" alias="Period Start" />
<ForeignKey pkSchema="Reports_vN" pkTable="payrec" fkSchema="Reports_vN" fkTable="tmcdln" name="Record Number">
<ForeignKeyCol pkCol="recnum" fkCol="recnum" />
</ForeignKey>
</Table>
</MyRoot>
2。彻底检查包括子元素和属性
我说,你最好的选择是使用Deserialization
。首先,您需要创建一组符合您的 XML
格式的 类。根据您提供的 XML
,它看起来像这样。请注意,我添加了一个 _root 节点,名为 MyRoot
.
[XmlRoot("MyRoot")]
public class MyRoot
{
[XmlElement("Table")]
public List<Table> Tables { get; set; }
}
public class Table
{
[XmlAttribute("schema")]
public string Schema { get; set; }
[XmlAttribute("name")]
public string Name { get; set; }
[XmlAttribute("caption")]
public string Caption { get; set; }
[XmlElement("Column")]
public List<Column> Columns { get; set; }
[XmlElement("ForeignKey")]
public List<ForeignKey> ForeignKeys { get; set; }
}
public class Column
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlAttribute("alias")]
public string Alias { get; set; }
[XmlAttribute("isprimarykey")]
public string IsPrimaryKey { get; set; }
}
public class ForeignKey
{
[XmlAttribute("pkSchema")]
public string PkSchema { get; set; }
[XmlAttribute("pkTable")]
public string PkTable { get; set; }
[XmlAttribute("fkSchema")]
public string FkSchema { get; set; }
[XmlAttribute("fkTable")]
public string FkTable { get; set; }
[XmlAttribute("name")]
public string Name { get; set; }
[XmlElement("ForeignKeyCol")]
public ForeignKeyCol ForeignKeyCol { get; set; }
}
public class ForeignKeyCol
{
[XmlAttribute("pkCol")]
public string PkCol { get; set; }
[XmlAttribute("fkCol")]
public string FkCol { get; set; }
}
现在,您可以使用以下方法反序列化您的XML
。
public static T DeserializeXMLFileToObject<T>(string XmlFilename)
{
T returnObject = default(T);
if (string.IsNullOrEmpty(XmlFilename)) return default(T);
try
{
StreamReader xmlStream = new StreamReader(XmlFilename);
XmlSerializer serializer = new XmlSerializer(typeof(T));
returnObject = (T)serializer.Deserialize(xmlStream);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return returnObject;
}
这样称呼它:
MyRoot xml = DeserializeXMLFileToObject<MyRoot>("data.xml");
现在需要使用简单的 C#
技术来查找和删除重复项。最简单的方法是写一个 Comparer
这样你就可以轻松地比较多个对象。