none
Getting the last xpathSelectElement().Attribute()?.Value c# RRS feed

  • Question

  • Hi,

    I asked a question at before:

     https://social.msdn.microsoft.com/Forums/vstudio/en-US/5c603b53-55c2-419e-9c59-6a2fd71ba35e/getting-an-xml-node-that-appears-more-than-once-linq-c?forum=csharpgeneral

    But I have made an error, not sure if I should ask on the above link as I marked it as answered so I'm asking a new one, hope this is ok...

    Here is my XML:

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE Racing SYSTEM "Racing.dtd">
    <Racing timestamp="20190322T150832+0100">
    <Meeting id="109" status="" date="20190322" Destination="UK">
    <Event id="88" status="" date="20190322" noContestants="5" time="1510+0100">
    <Contestant id="22" status="" name="Troy Mc Clean">
    <Shirt number="1"/>
    <Player id="11" name="Morgan Spice">
    </Player>
    <Coach id="13" name="John Smith"/>
    <Game timestamp="20190322T150333+0100" EventNumber="1">
    <Odds denom="8" numer="15"/>
    </Game>
    <Game timestamp="20190322T150539+0100" EventNumber="1">
    <Odds denom="4" numer="7"/>
    </Game>
    <Game timestamp="20190322T150546+0100" EventNumber="1">
    <Odds denom="8" numer="15"/>
    </Game>
    <Game timestamp="20190322T150703+0100" EventNumber="1">
    <Odds denom="1" numer="7"/>
    </Game>
    </Contestant>
    <Contestant></Contestant>
    <Contestant></Contestant>
    <Contestant></Contestant>
    <Contestant></Contestant>
    </Event>
    <Event></Event>
    <Event></Event>
    <Event></Event>
    </Meeting>
    </Racing>

    I am using XDocument and XPath, I would like to capture the:

    <Meeting Destination="UK",

    <Event time="1510" and noContestants="5"

    <Contestant status="" and name="Troy mc Clean" 

    <shirt number="1"

    <Player name="Morgan Spice"

    and the last <Game timestamp="20190322T150333+0100" and last <Odds numer="7" denom="1"

    Here is my code so far:

    var Elements = doc.XPathSelectElements("/Racing/Meeting"); var items = from m in Elements select new { dest = m.Attribute("Destination")?.Value, events = from e in m.XPathSelectElements("/Racing/Meeting/Event") select new { nocontest = e.Attribute("noContestants")?.Value, time = e.Attribute("time")?.Value, contestant = from c in m.XPathSelectElements("/Racing/Meeting/Event/Contestant") select new { contName = c.Attribute("name")?.Value, status = c.Attribute("status")?.Value, shirtNo = c.XPathSelectElement("Shirt").Attribute("number")?.Value, // Here I want to get the last timestamp from <Game and the last numer and denom from <Odds so it would

    be: timestamp="20190322T150703+0100" numer="7" denom="1"

    } } {


    Can someone show me how to get the part please? I have tried

    denom = c.XPathSelectElement("/Racing/Meeting/Event/Contestant/Game/[Odds ='denom'][position() =last()]").Attribute("denom")?.Value,

    There are lots of Contestants and Events, thank you for your help.


    CuriousCoder

    Wednesday, May 22, 2019 6:53 PM

Answers

  • In order to get the last “Odds” from the last “Game” and extract some details from parent elements, check this too:

    var last_odds = doc.XPathSelectElements( "/Racing/Meeting/Event/Contestant/Game[position()=last()]/Odds[position()=last()]" );
    
    var items = from odds in last_odds
                let game = odds.Parent
                let contestant = game.Parent
                let @event = contestant.Parent
                let meeting = @event.Parent
                let shirt = contestant.Element( "Shirt" )
                let player = contestant.Element( "Player" )
                let coach = contestant.Element( "Coach" )
                select new
                {
                    contName = contestant.Attribute( "name" ).Value,
                    player = player.Attribute( "name" ).Value,
                    numer = odds.Attribute( "numer" ).Value,
                    // . . .
                };
    

     

    Thursday, May 23, 2019 5:13 AM
  • Hi

    Thanks for the feedback.

    You could try the following change.

    Change

     denom = doc.Descendants("Odds").Last().Attribute("denom")?.Value,
     timestamp= doc.Descendants("Game").Last().Attribute("timestamp")?.Value,
     numer = doc.Descendants("Odds").Last().Attribute("numer")?.Value

    Into

    denom = c.Descendants("Odds").Last().Attribute("denom")?.Value,
    timestamp = c.Descendants("Game").Last().Attribute("timestamp")?.Value,
    numer = c.Descendants("Odds").Last().Attribute("numer")?.Value

    Best Regards,

    Jack


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Friday, May 24, 2019 2:12 AM
    Moderator

All replies

  • Hi CuriousCoder15,

    Thank you for posting here.

    For your question, you want to get the content that you wanted.

    I am not good at XPathSelectElement method, but I suggest that you could use Descendants method.

    You could try the following code.

    static void Main(string[] args)
            {
                var doc = XDocument.Load(@"D:\m.xml");
                var Elements = doc.XPathSelectElements("/Racing/Meeting");
                var items = from m in Elements
                            select new
                            {
                                dest = m.Attribute("Destination")?.Value,
    
                                events = from e in
                                m.XPathSelectElements("/Racing/Meeting/Event")
                                         select new
                                         {
                                             nocontest = e.Attribute("noContestants")?.Value,
                                             time = e.Attribute("time")?.Value,
    
                                             contestant = from c in
                                   m.XPathSelectElements("/Racing/Meeting/Event/Contestant")
                                                          select new
                                                          {
                                                              contName = c.Attribute("name")?.Value,
                                                              status = c.Attribute("status")?.Value,
                                                              shirtNo = c.XPathSelectElement("Shirt").Attribute("number")?.Value,
                                                              denom = doc.Descendants("Odds").Last().Attribute("denom")?.Value,
                                                              timestamp= doc.Descendants("Game").Last().Attribute("timestamp")?.Value,
                                                              numer = doc.Descendants("Odds").Last().Attribute("numer")?.Value
                                                          }
    
                                         }
    
                            };
                foreach (var element in items)
                {
                    foreach (var item in element.events)
                    {
                        foreach (var it in item.contestant)
                        {
                                Console.WriteLine(it.contName);
                                Console.WriteLine(it.status);
                                Console.WriteLine(it.shirtNo);
                                Console.WriteLine(it.denom);
                                Console.WriteLine(it.timestamp);
                                Console.WriteLine(it.numer);
                                return;
    
                        }
                    }
                }
            }

    Result:

    Best Regards,

    Jack


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, May 23, 2019 3:18 AM
    Moderator
  • In order to get the last “Odds” from the last “Game” and extract some details from parent elements, check this too:

    var last_odds = doc.XPathSelectElements( "/Racing/Meeting/Event/Contestant/Game[position()=last()]/Odds[position()=last()]" );
    
    var items = from odds in last_odds
                let game = odds.Parent
                let contestant = game.Parent
                let @event = contestant.Parent
                let meeting = @event.Parent
                let shirt = contestant.Element( "Shirt" )
                let player = contestant.Element( "Player" )
                let coach = contestant.Element( "Coach" )
                select new
                {
                    contName = contestant.Attribute( "name" ).Value,
                    player = player.Attribute( "name" ).Value,
                    numer = odds.Attribute( "numer" ).Value,
                    // . . .
                };
    

     

    Thursday, May 23, 2019 5:13 AM

  • Thank you for your answer.

    The doc.Descendants().Last() provides the very last instance of the denom and numer in the whole file, I would like to get the last instance of that node, so the result would be 1 denom and numer per contestant.

    Thank you



    CuriousCoder

    Thursday, May 23, 2019 10:02 AM
  • Hi

    Thanks for the feedback.

    You could try the following change.

    Change

     denom = doc.Descendants("Odds").Last().Attribute("denom")?.Value,
     timestamp= doc.Descendants("Game").Last().Attribute("timestamp")?.Value,
     numer = doc.Descendants("Odds").Last().Attribute("numer")?.Value

    Into

    denom = c.Descendants("Odds").Last().Attribute("denom")?.Value,
    timestamp = c.Descendants("Game").Last().Attribute("timestamp")?.Value,
    numer = c.Descendants("Odds").Last().Attribute("numer")?.Value

    Best Regards,

    Jack


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Friday, May 24, 2019 2:12 AM
    Moderator
  • I've never used the 'let' or 'into' keywords before so found this very interesting, it's not what I used in the end but it does work.

    CuriousCoder

    Monday, May 27, 2019 8:49 AM