如何使用 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 这样你就可以轻松地比较多个对象。