我正在建立一个数据库,包括会议,俱乐部,结果以及更多荷兰游泳运动员。由于我收到的数据发生了一些变化,我正在阅读我正在阅读的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">
已完全删除,我不需要任何内容。
如何将子节点从一个俱乐部移动到另一个俱乐部并删除空俱乐部?
有谁能指出我正确的方向?
(希望这一切都有道理......)
答案 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);