【问题标题】:Adding a new element to a XML file using LINQ XML (XDocument/XElement) using C#使用 C# 使用 LINQ XML (XDocument/XElement) 将新元素添加到 XML 文件
【发布时间】:2016-08-02 18:52:59
【问题描述】:

我正在尝试将新的 <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));

但不幸的是,没有创建新的&lt;Period&gt;&lt;/Period&gt; 元素。我检查了 XML 是否有效,确实如此。我尝试重命名元素,但没有改变。

我找不到解决方案,我错过了什么?

更新

嗯,这很尴尬:我重新启动了计算机和 VS,现在它可以工作了 - 去看看。尽管如此,还是感谢大家这么快的回复和建议。

【问题讨论】:

  • 你有没有检查过periodNodes.Add 确实被调用了?
  • 在询问我们之前,您可以use the debugger 单步执行您的代码并检查您的if 语句中的子句是否实际评估为真,如果不是,为什么不呢
  • 检查this fiddle - 你的代码工作正常。如果您仍有问题,请提供minimal reproducible example
  • @Charles Mager:我确实做到了,它确实进入了 periodNodes.Add 行。该文件也被保存(检查日期时间戳),但仍然缺少该行。

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


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    使用此代码

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

    【讨论】:

    • 这消除了一堆关于何时何地添加句点的逻辑。而且,作为问题actually works fine 中的代码,目前尚不清楚这将如何解决问题。
    • @user1224125 查看我的最新更新希望这是你想要的
    【解决方案3】:

    知道您已经解决了问题,但您可以使用 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创建的工作版本

    【讨论】:

      【解决方案4】:

      在使用 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")
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-07-21
        • 2023-03-24
        • 1970-01-01
        • 2022-01-18
        • 2014-09-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多