1

私は、オランダの水泳選手のために、大会、クラブ、結果などを含むデータベースを構築しています。受信しているデータにいくつかの変更があったため、読み取っている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、同じ値をデータベースに2回書き込もうとしているため、エラーが発生します。

だから私がやりたいのは、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>
        <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>

2番目のクラブノード<CLUB name="A.Z.V.D." type="CLUB" nation="NED" region="8" code="08-004">が完全に削除されていることに注意してください。そのノードからは何も必要ありません。子ノードをあるクラブから別のクラブに移動し、空のクラブを削除するにはどうすればよいですか?私を正しい方向に向けることができる人はいますか?

(これがすべて理にかなっていることを願っています....)

4

1 に答える 1

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);

そして、それはあなたが要求した結果を返します。

子ノードを結合する場合に備えて、すべてが結合されたXElementのリストを返すextensionメソッドがあります。たとえば、同一のCLUB要素を組み合わせた後、1つ以上のCLUBに2つ以上の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);
于 2012-10-13T00:21:24.240 に答える