使用C#使用LINQ XML(XDocument / XElement)将新元素添加到XML文件

时间:2016-08-02 18:52:59

标签: c# xml linq linq-to-xml xelement

我正在尝试将新的<Period></Period>元素添加(插入)到以下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>

例如,我传递值96,新的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>
      <Period>96</Period>
    </Schedule>
  </Module>
</Scheduler>

使用以下代码;

// 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));

但遗憾的是,没有创建新的<Period></Period>元素。我已经检查过XML是否有效。我尝试重命名元素,但没有改变。

我找不到解决方案,我缺少什么?

更新

嗯,这很令人尴尬:我重新启动了计算机和VS,现在它可以正常工作了。尽管如此,感谢大家的快速回复和建议。

4 个答案:

答案 0 :(得分:1)

请确保不要在另一个应用程序中打开该文件,并且运行该应用程序的帐户有权写入该文件。尝试创建一个新文件,这将消除文件写访问;除非用户帐户对该目录没有写入权限。

出于测试目的,尝试将最后一行更改为此...


@java -cp %~dp0..\ClassLib\antlr-4.5-complete.jar;%CLASSPATH% org.antlr.v4.Tool %*

答案 1 :(得分:0)

使用此代码

        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));
        }

答案 2 :(得分:0)

知道您已经找到了问题,但是您可以通过使用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));
}

您可以在.NET Fiddle here

上看到我创建的工作版本

答案 3 :(得分:0)

在使用XElement的VB中,它看起来像这样,

    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")