1

I want to delete all the duplicate Bet elements from the MatchOdds nodes except the last one from the following xml sample and than save the file in another destination.

<Sports>
  <Sport id="5" name="Tennis">
    <Tournament id="3" name="ATP - Basel, Switzerland">
      <Match id="8331188" name="Nadal, Rafael v Gasquet, Richard" 
          startDate="2015-10-31T13:30:00">
        <MatchOdds>
          <Bet id="20">
            <Outcome Special="" name="1" odds="1.35" />
            <Outcome Special="" name="2" odds="3.3" />
          </Bet>
          <Bet id="204">
            <Outcome Special="" name="1" odds="1.45" />
            <Outcome Special="" name="2" odds="2.85" />
          </Bet>
          <Bet id="231">
            <Outcome Special="" name="1" odds="1.45" />
            <Outcome Special="" name="2" odds="2.75" />
          </Bet>
          <Bet id="206">
            <Outcome Special="" name="2 sets" odds="1.55" />
            <Outcome Special="" name="3 sets" odds="2.35" />
          </Bet>
          <Bet id="233">
            <Outcome Special="" name="2:0" odds="1.9" />
            <Outcome Special="" name="2:1" odds="3.5" />
            <Outcome Special="" name="0:2" odds="5.75" />
            <Outcome Special="" name="1:2" odds="6.0" />
          </Bet>
          <Bet id="233">
            <Outcome Special="" name="2:0" odds="1.9" />
            <Outcome Special="" name="2:1" odds="3.5" />
            <Outcome Special="" name="0:2" odds="5.75" />
            <Outcome Special="" name="1:2" odds="6.0" />
          </Bet>
          <Bet id="233">
            <Outcome Special="" name="2:0" odds="1.9" />
            <Outcome Special="" name="2:1" odds="3.5" />
            <Outcome Special="" name="0:2" odds="5.75" />
            <Outcome Special="" name="1:2" odds="6.0" />
          </Bet>
          <Bet id="233">
            <Outcome Special="" name="2:0" odds="1.9" />
            <Outcome Special="" name="2:1" odds="3.5" />
            <Outcome Special="" name="0:2" odds="5.75" />
            <Outcome Special="" name="1:2" odds="6.0" />
          </Bet>
          <Bet id="233">
            <Outcome Special="" name="2:0" odds="1.9" />
            <Outcome Special="" name="2:1" odds="3.5" />
            <Outcome Special="" name="0:2" odds="5.75" />
            <Outcome Special="" name="1:2" odds="6.0" />
          </Bet>
          <Bet id="233">
            <Outcome Special="" name="2:0" odds="12312333322" />
            <Outcome Special="" name="2:1" odds="123123" />
            <Outcome Special="" name="0:2" odds="123123123" />
            <Outcome Special="" name="1:2" odds="123123123" />
          </Bet>
        </MatchOdds>
      </Match>
    </Tournament>
  </Sport>
</Sports>

I want to do it using LINQ - to - XMl(Xdocument class), but I don't know how. Can you please help me with that query? Thanks in advance

spender
  • 117,338
  • 33
  • 229
  • 351
IT efbet
  • 61
  • 6
  • 3
    So you've posted broken XML: The 'Match' start tag on line 4 position 10 does not match the end tag of 'Tournament'. Line 59, position 7. – spender Nov 13 '15 at 12:46
  • I took the liberty of fixing and reformatting your XML. – spender Nov 13 '15 at 13:14

2 Answers2

2

You can try grouping by id, and later in case some group have more than one element delete the first count-1 elements:

   var query = from el in doc.Descendants("Bet")
               group el by el.Attribute("id").Value;

   foreach (var g in query)
   {
      int count=g.Count();
      if (count>1)
      {
         g.Take(count - 1).Remove();// remove every node in the source collection from its parent node
      }
   }
ocuenca
  • 38,548
  • 11
  • 89
  • 102
1

It's not clear what you mean by identical... In the absence of a better definition of identical, I'm going to assume here that all bet elements are identical.

Assuming that you're using a non-broken version of the XML you quoted above:

var bets = doc.Root.Descendants("MatchOdds").Descendants("Bet").ToList();
var lastBet = bets.Last();

foreach(var bet in bets)
{
    if(bet != lastBet)
    {
        bet.Remove();
    }
}

Now a more sensible definition of "identical" might be ones that share the same id.

I'd choose here to use a WithoutLast extension method I keep handy:

static class Ex
{
    public static IEnumerable<T> WithoutLast<T>(this IEnumerable<T> source)
    {
        using (var e = source.GetEnumerator())
        {
            if (e.MoveNext())
            {
                for (var value = e.Current; e.MoveNext(); value = e.Current)
                {
                    yield return value;
                }
            }
        }
    }
}

then you can have this lovely LINQy solution to the problem:

var bets = doc.Root.Descendants("MatchOdds").Descendants("Bet");
var betsToRemove = bets.GroupBy(b => (string)b.Attribute("id"))
                       .SelectMany(g => g.WithoutLast())
                       .ToList();
betsToRemove.ForEach(b => b.Remove());
Community
  • 1
  • 1
spender
  • 117,338
  • 33
  • 229
  • 351