C# - LinQ query take it, save it problem

Markus Freitag 3,786 Reputation points
2021-01-15T13:22:49.06+00:00

Hello,

I need to read in an xml file and need to take out n elements and save them again.
Sample:

   TakeElements(int count);
  Call with TakeElements(5);


 <SERIALS>
   <POS index="1" content="AAA5SUU" processed="false"/>
   <POS index="2" content="AAA5SUV" processed="false"/>
   <POS index="3" content="AAA5SUW" processed="false"/>


   <POS index="1000" content="AAA5SVL" processed="false"/>
 </SERIALS>

After save it.

<SERIALS>
  <POS index="1" content="AAA5SUU" processed="true"/>
  <POS index="2" content="AAA5SUV" processed="true"/>
  <POS index="3" content="AAA5SUW" processed="true"/>
  <POS index="4" content="AAA5SVL" processed="false"/>


  <POS index="999" content="AAA5SVL999" processed="false"/>
  <POS index="1000" content="AAA5SVL1000" processed="false"/>
</SERIALS>

if the amount is no longer sufficient, error message. Example. I want to have 5, there are only 2 available.
How do I query this? Like this.

<SERIALS>
  <POS index="1" content="AAA5SUU" processed="true"/>
  <POS index="2" content="AAA5SUV" processed="true"/>
  <POS index="3" content="AAA5SUW" processed="true"/>
  <POS index="4" content="AAA5SVL" processed="true"/>

  <POS index="998" content="AAA5SVL998" processed="true"/>
  <POS index="999" content="AAA5SVL999" processed="false"/>
  <POS index="1000" content="AAA5SVL1000" processed="false"/>
</SERIALS>

If the amount is no longer sufficient, the file must be moved.
C:\Share\Work\
C:\Share\IsDone\

C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,098 questions
0 comments No comments
{count} votes

Accepted answer
  1. Yitzhak Khabinsky 24,831 Reputation points
    2021-01-15T14:26:19.16+00:00

    Something along the following.

    Solution #1
    If you need to create a completely new XML file.

    void Main()
    {
     const string SERIALS = "SERIALS";
     const string POS = "POS";
     const string PROCESSED = "processed";
     const string FALSE = "false";
     const string TRUE = "true";
    
     int TakeElements = 2;
     int posCounter = 0;
     string outputXMLfile = @"C:\Share\IsDone\outputXMLfile.xml";
    
     // just use .Load(filePath) for your real life scenario
     XDocument xdoc = XDocument.Parse(@"<SERIALS>
     <POS index='1' content='AAA5SUU' processed='false'/>
     <POS index='2' content='AAA5SUV' processed='false'/>
     <POS index='3' content='AAA5SUW' processed='false'/>
     <POS index='1000' content='AAA5SVL' processed='false'/>
     </SERIALS>");
    
     posCounter = xdoc.Root.Descendants(POS)
     .Where(r => r.Attribute(PROCESSED).Value.Equals(FALSE))
     .Count();
    
     if (posCounter >= TakeElements)
     {
     // construct new XML document
     XDocument newXDoc = new XDocument(new XElement(SERIALS));
    
     // get first TakeElements elements where processed='false'
     foreach (var element in xdoc.Root.Descendants(POS)
     .Where(r => r.Attribute(PROCESSED).Value.Equals(FALSE))
     .Take(TakeElements))
     {
     // set attribute value
     element.Attribute(PROCESSED).SetValue(TRUE);
     // add element to the document
     newXDoc.Root.Add(element);
     }
     // save final XML document
     // uncomment when you are ready
     //newXDoc.Save(outputXMLfile);
     }
     else
     {
     // do something else
     }
    }
    

    Solution #2
    If you need to modify the original file.

    void Main()
    {
     const string SERIALS = "SERIALS";
     const string POS = "POS";
     const string PROCESSED = "processed";
     const string FALSE = "false";
     const string TRUE = "true";
    
     int TakeElements = 2;
     int posCounter = 0;
     string outputXMLfile = @"C:\Share\IsDone\outputXMLfile.xml";
    
     // just use .Load(filePath) for your real life scenario
     XDocument xdoc = XDocument.Parse(@"<SERIALS>
     <POS index='1' content='AAA5SUU' processed='false'/>
     <POS index='2' content='AAA5SUV' processed='false'/>
     <POS index='3' content='AAA5SUW' processed='false'/>
     <POS index='1000' content='AAA5SVL' processed='false'/>
     </SERIALS>");
    
     posCounter = xdoc.Root.Descendants(POS)
     .Where(r => r.Attribute(PROCESSED).Value.Equals(FALSE))
     .Count();
    
     if (posCounter >= TakeElements)
     {
     // get first TakeElements elements where processed='false'
     foreach (var element in xdoc.Root.Descendants(POS)
     .Where(r => r.Attribute(PROCESSED).Value.Equals(FALSE))
     .Take(TakeElements))
     {
     // set attribute value
     element.Attribute(PROCESSED).SetValue(TRUE);
     }
     // save final XML document
     // uncomment when you are ready
     //xdoc.Save(outputXMLfile);
     }
     else
     {
     // do something else
     }
    }
    

0 additional answers

Sort by: Most helpful