将2个重复的xml节点合并为一个

时间:2012-10-12 22:19:15

标签: c# xml

我正在建立一个数据库,包括会议,俱乐部,结果以及更多荷兰游泳运动员。由于我收到的数据发生了一些变化,我正在阅读我正在阅读的XML文件中存在重复值的问题。

以下是导致问题的XML文件的一部分:

<LENEX version="3.0">
  <MEETS>
    <MEET name="Speedowedstrijd 2012 - 2013 deel 1">
      <CLUB name="AZVD" type="CLUB" nation="NED" region="08" code="08-004">
        <OFFICIALS>
          <OFFICIAL nation="NED" gender="M" officialid="2329" lastname="xx">
            <CONTACT email="xx" phone="xx" country="NL" />
          </OFFICIAL>
        </OFFICIALS>
      </CLUB>
      <CLUB name="A.Z.V.D." type="CLUB" nation="NED" region="8" code="08-004">
        <ATHLETES>
          <ATHLETE nation="NED" gender="M" athleteid="2358" license="xx" lastname="xx">
            <RESULTS>
              <RESULT eventid="1167" resultid="2359" swimtime="00:03:09.69">
                <SPLITS>
                  <SPLIT distance="50" swimtime="00:00:40.71"/>
                  <SPLIT distance="100" swimtime="00:01:30.71"/>
                </SPLITS>
              </RESULT>
            </RESULTS>
          </ATHLETE>
        </ATHLETES>
      </CLUB>
    </MEET>
  </MEETS>
</LENEX>

现在读取xml文件不是问题,使用XDocument我得到所有节点,子节点等。 但是,当我将值写入我的数据库时,我在表Club_Meet上得到了keyconstraint错误。该表保存了球杆桌和会面桌之间的链接,每个组合必须是唯一的。由于上面示例中的两个俱乐部都指向我的数据库中的同一个俱乐部(唯一代码= 08-004,我试图将相同的值写入数据库两次,导致错误。

所以我想要做的是当我浏览xml文件并找到一个俱乐部时:检查此俱乐部之前是否已找到此俱乐部,如果是这样,则将该子节点挂在该第一个俱乐部节点下。 此操作的结果应该是(内部):

<LENEX version="3.0">
  <MEETS>
    <MEET name="Speedowedstrijd 2012 - 2013 deel 1">
      <CLUB name="AZVD" type="CLUB" nation="NED" region="08" code="08-004">
        <OFFICIALS>
          <OFFICIAL nation="NED" gender="M" officialid="2329" lastname="xx">
            <CONTACT email="xx" phone="xx" country="NL" />
          </OFFICIAL>
        </OFFICIALS>
        <ATHLETES>
          <ATHLETE nation="NED" gender="M" athleteid="2358" license="xx" lastname="xx">
            <RESULTS>
              <RESULT eventid="1167" resultid="2359" swimtime="00:03:09.69">
                <SPLITS>
                  <SPLIT distance="50" swimtime="00:00:40.71"/>
                  <SPLIT distance="100" swimtime="00:01:30.71"/>
                </SPLITS>
              </RESULT>
            </RESULTS>
          </ATHLETE>
        </ATHLETES>
      </CLUB>
    </MEET>
  </MEETS>
</LENEX>

请注意,第二个俱乐部节点<CLUB name="A.Z.V.D." type="CLUB" nation="NED" region="8" code="08-004">已完全删除,我不需要任何内容​​。 如何将子节点从一个俱乐部移动到另一个俱乐部并删除空俱乐部? 有谁能指出我正确的方向?

(希望这一切都有道理......)

1 个答案:

答案 0 :(得分:1)

好的,如果您想严格操作XML文档,可以使用我创建的以下扩展方法。

public static class XmlExtensions
{
   public static IEnumerable<XElement> CombineLikeElements(this IEnumerable<XElement> source, Func<XElement, object> groupSelector)
   {
      // used to record the newly combined elements
      List<XElement> priElements = new List<XElement>();

      // group the current xml nodes by the supplied groupSelector, and only
      // select the groups that have more than 1 elements.
      var groups = source.GroupBy(groupSelector).Where(grp => grp.Count() > 1);

      foreach(var grp in groups)
      {
         // get the first (primary) child element and use it as 
         // element that all the other sibling elements get combined with.
         var priElement = grp.First();

         // get all the sibling elements which will be combined
         // with the primary element.  Skipping the primary element.
         var sibElements = grp.Skip(1);

         // add all the sibling element's child nodes to the primary
         // element.
         priElement.Add(sibElements.Select(node => node.Elements()));

         // remove all of the sibling elements
         sibElements.Remove();

         // add the primary element to the return list
         priElements.Add(priElement);
      }

      // return the primary elements incase we want to do some further
      // combining of their descendents
      return priElements;
   }
}

您可以按如下方式使用扩展方法:

XDocument xmlDoc = XDocument.Parse(xml);
xmlDoc
   // Combine all of the duplicate CLUB nodes under each MEET node
   .Descendants("MEET").Descendants("CLUB").CombineLikeElements(node => node.Attribute("code").Value);

它将返回您请求的结果。

我有扩展方法返回一个XElements列表,如果你想要组合他们的子节点,那么所有内容都被合并到一起。例如,如果在组合相同的CLUB元素后,一个或多个CLUB最终具有两个或更多ATHLETES或OFFICIALS节点,您可以通过执行以下操作轻松地将它们组合在一起:

xmlDoc
   // Combine all of the duplicate CLUB nodes under each MEET node
   .Descendants("MEET").Descendants("CLUB").CombineLikeElements(node => node.Attribute("code").Value)
   // Combine all of the duplicate ALTHLETES or OFFICIALS nodes under the newly combined CLUB nodes
   .Elements().CombineLikeElements(node => node.Name);