Как устранить дубликаты узлов XML с помощью кода C # - PullRequest
0 голосов
/ 05 сентября 2018

У меня есть XML-файл схемы, который содержит узлы для Table, Columns и ForeignKeys, как показано ниже.

<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.

1 Ответ

0 голосов
/ 05 сентября 2018

Прежде всего, ваш 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, чтобы вы могли легко сравнивать несколько объектов.

...