none
[LINQ] How can I get "every" last value ? RRS feed

  • Question

  •  I have XML contents like this.

    <LanguageFiles>
      <LanguageFile LanguageCode="English">
         <FileVersions>
            <FileVersion VersionNumber="1" FileName="Foo1" />
    	<FileVersion VersionNumber="2" FileName="Foo1" />
         </FileVersions>
      </LanguageFile>
      <LanguageFile LanguageCode="Korean">
          <FileVersions>
            <FileVersion VersionNumber="1" FileName="Boo1" />
            <FileVersion VersionNumber="2" FileName="Boo1" />
          </FileVersions>
       </LanguageFile>
    </LanguageFiles>

    I'd like to have my result like this.
          Boo1 (for the current code, only, but the same style goes on and on..)
          Boo2
          Boo3..

     So, I wrote my code.

    var FNs = XDocument.Load(myPath)
    	.Descendants("LanguageFile").Where((x, i) => i % 2 == 1)
    	.Descendants("FileVersion").Where((x, i) => i % 2 == 1)
    	.Attributes("FileName");
    MessageBox.Show(string.Join("\n", FNs.Select(x => x.Value)));

    It works though it is not general (it uses 'even' trick).
    The 'FileVersion' will be added.
    In that case the "even number" code will have problem.
    Because, I need the last file version.

    So, I tried this one to get "every" 2nd and the last values from it.
    (yes, it does not make what I wanted, it is a garbage.)

    var FNs = XDocument.Load(myPath)
    	.Descendants("LanguageFile").Element(1)
    	.Descendants("FileVersion").Last()
    	.Attributes("FileName");
    MessageBox.Show(string.Join("\n", FNs.Select(x => x.Value)));

    Help please !!












    Tuesday, March 20, 2018 5:47 AM

Answers

  • It is clear that the folks in the forum do not understand what you're asking for. There is only 1 last item in anything. There can be a last item in each group of things but you haven't defined what that grouping is.

    I'm going to guess that you either want the last FileVersion in each FileVersions node or you want the last FileVersion in the entire XML. Here's methods for both.

    static IEnumerable<XElement> GetLastFileVersionOfEveryLanguageFile ( XDocument doc )
    {
        //Get every file version group
        var fileVersions = doc.Root.XPathSelectElements("//FileVersions");
    
        //Get the last FileVersion for each group
        foreach (var e in fileVersions)
        {
            var fileVersion = e.Descendants("FileVersion").LastOrDefault();
            if (fileVersion != null)
                yield return fileVersion;
        };
    }
    
    static XElement GetLastFileVersionOfLanguageFiles ( XDocument doc )
    {
        return doc.Root.XPathSelectElements("//FileVersion").LastOrDefault();
    }

    If that does not answer your question then please do the following.

    1) Provide a full, valid XML example that contains multiple sets of elements from which you're reading.

    2) The exact output you expect for the XML you post.

    3) What the methods aren't doing that you need them to do.

    If you are expecting multiple records back then we need to see the XML that produces those multiple records. Partial XML will not give us the full picture to produce the correct query that works in a larger XML document and will simply delay you getting an answer you can use. Thanks.


    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, March 21, 2018 1:51 PM
    Moderator

All replies

  • What do you mean by every last value. Please post the XML you have and the exact output you are wanting along with any rules you have that determines the values to retrieve.

    Michael Taylor http://www.michaeltaylorp3.net

    Tuesday, March 20, 2018 2:14 PM
    Moderator
  • thanks reply

    I have posted a part of XML

    I have posted the result I wanted (it shows the 'last')

    regards

    Tuesday, March 20, 2018 3:13 PM
  • So for each XML file you want to get the last FileName of the last FileVersion of the last LanguageFile?  There is no boo2 or boo3 so I don't understand where those values are coming from. Given the XML it seems you don't care about the language or whatnot and just want the last which would eliminate Foo1.

    If there are conditions (i.e. I want the last FileName of the last FileVersion of each of the LanguageFile) then please explain those rules as well.


    Michael Taylor http://www.michaeltaylorp3.net

    Tuesday, March 20, 2018 3:46 PM
    Moderator
  • Yes, I'd like to grab "the last" FileVersion element.
    -the Language file is, on second thought, does not matter (because, there will be no way better than this '%' style)

    Yes, there is no boo2 and boo3 on your monitor.
    Because it belongs repeated part of XML
    - it should be waste of time and space to write that thing.
    That is mainly repeated so many times - that is why I use LINQ.

    regards

    - ah, thanks for the reply again, I've thought you are just one of the stubborn moderators found everywhere-looks like I was wrong.
    Wednesday, March 21, 2018 6:37 AM
  • let me write again my point

    "How can I grab EVERY last item using LINQ"

    Wednesday, March 21, 2018 6:39 AM
  • Check this example:

    using System.Xml.XPath;
    . . .
    
    string xml = @"
        <LanguageFiles>
            <LanguageFile LanguageCode=""English"">
                <FileVersions>
                    <FileVersion VersionNumber=""1"" FileName=""Foo"" />
                    <FileVersion VersionNumber=""2"" FileName=""Last1"" />
                </FileVersions>
            </LanguageFile>
            <LanguageFile LanguageCode=""Korean"">
                <FileVersions>
                    <FileVersion VersionNumber=""1"" FileName=""Last2"" />
                </FileVersions>
            </LanguageFile>
            <LanguageFile LanguageCode=""Albanian"">
                <FileVersions>
                    <FileVersion VersionNumber=""1"" FileName=""Foo"" />
                    <FileVersion VersionNumber=""3"" FileName=""Last3"" />
                    <FileVersion VersionNumber=""2"" FileName=""Foo"" />
                </FileVersions>
            </LanguageFile>
        </LanguageFiles>";
    
    var doc = XDocument.Parse( xml );
    var filenames = doc.XPathSelectElements( "/*/LanguageFile/FileVersions/FileVersion[not(@VersionNumber < preceding-sibling::FileVersion/@VersionNumber) and not(@VersionNumber < following-sibling::FileVersion/@VersionNumber)]" ).Select( e => e.Attribute( "FileName" ).Value );
    
    MessageBox.Show( string.Join( "\r\n", filenames ) );
    

    Wednesday, March 21, 2018 8:20 AM
  • Hello ,

    >>"How can I grab EVERY last item using LINQ"

    You could try the Descendants directly like below.

      XDocument xml = XDocument.Load("../../XMLFile2.xml");
    
    
      var re = xml.Descendants("FileVersion").Last().Attribute("FileName");

    Best regards,

    Neil Hu


    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.

    Wednesday, March 21, 2018 9:09 AM
    Moderator
  • you lost "EVERY" part

    thanks

    Wednesday, March 21, 2018 1:20 PM
  • that's not the point

    regards



    Wednesday, March 21, 2018 1:22 PM
  • It is clear that the folks in the forum do not understand what you're asking for. There is only 1 last item in anything. There can be a last item in each group of things but you haven't defined what that grouping is.

    I'm going to guess that you either want the last FileVersion in each FileVersions node or you want the last FileVersion in the entire XML. Here's methods for both.

    static IEnumerable<XElement> GetLastFileVersionOfEveryLanguageFile ( XDocument doc )
    {
        //Get every file version group
        var fileVersions = doc.Root.XPathSelectElements("//FileVersions");
    
        //Get the last FileVersion for each group
        foreach (var e in fileVersions)
        {
            var fileVersion = e.Descendants("FileVersion").LastOrDefault();
            if (fileVersion != null)
                yield return fileVersion;
        };
    }
    
    static XElement GetLastFileVersionOfLanguageFiles ( XDocument doc )
    {
        return doc.Root.XPathSelectElements("//FileVersion").LastOrDefault();
    }

    If that does not answer your question then please do the following.

    1) Provide a full, valid XML example that contains multiple sets of elements from which you're reading.

    2) The exact output you expect for the XML you post.

    3) What the methods aren't doing that you need them to do.

    If you are expecting multiple records back then we need to see the XML that produces those multiple records. Partial XML will not give us the full picture to produce the correct query that works in a larger XML document and will simply delay you getting an answer you can use. Thanks.


    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, March 21, 2018 1:51 PM
    Moderator
  • I saw the two members reply. The are just telling the basic story. One is attribute's value the other is Last() method. Nobody here asking the basic information. I read several books (for the beginning readres), so I can say cleary, I know basic of it.

    I'll chek out your reply with leisure.

    regards

    Wednesday, March 21, 2018 1:58 PM
  • you used XPath

    I'm not familiar with it (because, I read all about XDOM and xmlDocument)

    any ways, I'll check it out

    regards

    Wednesday, March 21, 2018 2:05 PM
  • ok

    that's fine

    I've tried to use LINQ exclusively

    but, I change my mind

    whatever it is, I will use

    so

    your tip, works

    thanks...

    Wednesday, March 21, 2018 2:37 PM
  • too easy

    thanks again

    Wednesday, March 21, 2018 3:52 PM