user1224125
user1224125

Reputation: 21

Adding a new element to a XML file using LINQ XML (XDocument/XElement) using C#

I am trying to add (insert) a new <Period></Period> element into the following XML;

<?xml version="1.0" encoding="utf-8"?>
<Scheduler>
  <Module guid="64A3EB4C-7F34-47F3-8894-933CB0048D87">
    <RetrieveDays>1</RetrieveDays>
    <Schedule>
      <Period>1</Period>
      <Period>33</Period>
      <Period>49</Period>
      <Period>73</Period>
    </Schedule>
  </Module>
</Scheduler>

So for example, I pass the value 96, the new XML would look like;

<?xml version="1.0" encoding="utf-8"?>
<Scheduler>
  <Module guid="64A3EB4C-7F34-47F3-8894-933CB0048D87">
    <RetrieveDays>1</RetrieveDays>
    <Schedule>
      <Period>1</Period>
      <Period>33</Period>
      <Period>49</Period>
      <Period>73</Period>
      <Period>96</Period>
    </Schedule>
  </Module>
</Scheduler>

Using the following code;

// period is the new value
XDocument xmlDoc = new XDocument();
xmlDoc = XDocument.Load(String.Format(@"{0}\{1}", settingsDir, settingsFilename));
XElement periodNodes = xmlDoc.Root.Descendants("Module").Where(i => (String)i.Attribute("guid") == moduleGuId).First().Element("Schedule");

if (periodNodes.Descendants("Period").Where(x => x.Value == period.ToString()).Count() == 0)
    periodNodes.Add(new XElement("Period", period.ToString()));

xmlDoc.Save(String.Format(@"{0}\{1}", settingsDir, settingsFilename));

But unfortunately no new <Period></Period> element gets created. I have checked that the XML is valid, which it is. I tried renaming the element, but to no change.

I cannot find a solution, what am I missing?

Update

Well, this is embarrassing: I restarted the computer and VS and now it works - go figure. Nonetheless, thank you all for such quick responses and suggestions.

Upvotes: 0

Views: 1116

Answers (4)

dbasnett
dbasnett

Reputation: 11773

In VB using XElement it would look like this,

    Dim xe As XElement
    'to load from a file
    '  xe = XElement.Load("Your Path Here")

    ' for testing
    xe = <Scheduler>
             <Module guid="64A3EB4C-7F34-47F3-8894-933CB0048D87">
                 <RetrieveDays>1</RetrieveDays>
                 <Schedule>
                     <Period>1</Period>
                     <Period>33</Period>
                     <Period>49</Period>
                     <Period>73</Period>
                 </Schedule>
             </Module>
         </Scheduler>

    Dim moduleGuId As String = "64A3EB4C-7F34-47F3-8894-933CB0048D87"
    Dim theVal As Integer = 96

    Dim ie As IEnumerable(Of XElement)
    ie = From el In xe.<Module> Where el.@guid = moduleGuId Take 1
         From sel In el.<Schedule>...<Period> Where sel.Value = theVal.ToString Select sel

    If ie.Count = 0 Then
        xe...<Schedule>.LastOrDefault.Add(<Period><%= theVal %></Period>)
    End If

    '  xe.Save("path here")

Upvotes: 0

konkked
konkked

Reputation: 3231

Know that you've figured out the issue but you can eliminate a lot of your code by using XPath.

var schedulerSelect = string.Format("//Module[@guid='{0}']/Schedule",guid);
var periodSelect = string.Format("Period[text()={0}]",period);
var node = doc.XPathSelectElement(schedulerSelect+"/"+periodSelect);

if(node == null)
{
    node = doc.XPathSelectElement(schedulerSelect);

    if(node!=null)
       node.Add(new XElement("Period",period));
}

You can see a working version I created on .NET Fiddle here

Upvotes: 1

Mostafiz
Mostafiz

Reputation: 7352

Use this code

        XDocument doc = XDocument.Load(String.Format(@"{0}\{1}", settingsDir, settingsFilename));
        var query = doc.Descendants("Schedule");
        var q2 = query.Descendants("Period").Where(a => a.Value == period.ToString()).Select(b => b);

        if (q2.Count() == 0)
        {
            query.FirstOrDefault().Add(new XElement("Period", period.ToString()));
            doc.Save(String.Format(@"{0}\{1}", settingsDir, settingsFilename));
        }

Upvotes: 0

Larry Dukek
Larry Dukek

Reputation: 2199

Be sure not to have the file open in another application and that the account the application is running under has rights to write to that file. Try creating a new file instead, this will eliminate the file write access; unless the user account doesn't have write permissions on that directory.

For testing purposes try changing the final line to this...

xmlDoc.Save(String.Format(@"{0}\{1}2", settingsDir, settingsFilename));

Upvotes: 1

Related Questions