【问题标题】:Xml updating with linq not working when quering查询时使用 linq 更新 Xml 不起作用
【发布时间】:2012-10-10 09:27:10
【问题描述】:

我有一个问题,我正在尝试使用 linq 查询更新 XML 的特定部分,但它不起作用。所以我是一个 xml 文件:

<?xml version="1.0" encoding="utf-8"?>
<DesignConfiguration>
  <Design name="CSF_Packages">
    <SourceFolder>C:\CSF_Packages</SourceFolder>
    <DestinationFolder>C:\Documents and Settings\xxx</DestinationFolder>
    <CopyLookups>True</CopyLookups>
    <CopyImages>False</CopyImages>
    <ImageSourceFolder>None</ImageSourceFolder>
    <ImageDesinationFolder>None</ImageDesinationFolder>
  </Design>
</DesignConfiguration>

我想选择存在Design name="somethning"的部分并获取后代,然后更新表示该部分的后代值:

    <SourceFolder>C:\CSF_Packages</SourceFolder>
    <DestinationFolder>C:\Documents and Settings\xxx</DestinationFolder>
    <CopyLookups>True</CopyLookups>
    <CopyImages>False</CopyImages>
    <ImageSourceFolder>None</ImageSourceFolder>
    <ImageDesinationFolder>None</ImageDesinationFolder>

我有这个代码:

        XDocument configXml = XDocument.Load(configXMLFileName);

        var updateData = configXml.Descendants("DesignConfiguration").Elements().Where(el => el.Name == "Design" &&
            el.Attribute("name").Value.Equals("CSF_Packages")).FirstOrDefault();

        configXml.Save(configXMLFileName);

我在updateData 变量中获取空数据。当我通过 QuickWatch 尝试 Descendat 的功能时,它也返回一个空值。当我检查 configXML 变量时,它的数据就是我的整个 xml。我究竟做错了什么?

【问题讨论】:

  • 你真的有一个元素的name 属性的值为“AFP_GRAFIKA”吗?在您的示例中,该属性的唯一值是“CSF_Packages”...
  • 是的,因为我正在测试一些东西,我给了你我正在尝试的东西的代码,对此感到抱歉。
  • 没关系,您的示例一切正常,但我注意到如果您搜索“CSF_Packages”而不是“AFP_GRAFIKA”,您的代码会检索 XML,所以我认为可能是具有属性 @值为“AFP_GRAFIKA”的 987654327@ 的路径与 DesignConfiguration\Design 不同。
  • 我确实搜索过这个,但它仍然不起作用。问题是,无论我要求什么,后代函数都返回 null 。所以我猜当它为空时没有什么可以检索的。我将更新帖子,以免对此造成混淆:)

标签: c# xml linq


【解决方案1】:

试试这个:

var updateData = 
    confixXml
    .Root                     //Root Element
    .Elements("Design")       //All elements under root called Design
    .Where(element => (String)element.Attribute("name") == "AFP_GRAFIKA") //Find the one with the name Attribute of AFP_GRAFIKA
    .FirstOrDefault();        //Grab the first one it finds or return null.

if (updateData != null)
{
    var myElements = 
        updateData
        .Elements();          //All the elements under the Design node
}

【讨论】:

  • 这行得通!!! :) 非常感谢你。最后一件事你能解释一下为什么我的灵魂不起作用以及我在 StacOverFlow 上找到的其他灵魂吗?因为我有类似的例子,但它们似乎不起作用。
  • 我想知道不,如何通过 foreach 循环更新里面的元素?然后保存到xml?
  • 是的,这是最好的方法,
  • 但是在集合中我有树元素如何一一更改?这个具有上述解决方案的函数有一个参数,它是一个对象。这有像 SourceFolder 这样的属性,所以,我想根据这些数据来改变它。但是,如果我理解正确,我只能更改集合中的一项并将对象属性中的数据分配给该项。希望这是可以理解的:)
【解决方案2】:
XDocument xml = XDocument.Load("");

XElement settings = (from children in xml.Descendants("DesignConfiguration")
                        where children.Name.Equals("Design") && children.Attribute("name").Equals("CSF_Packages")
                        select children).FirstOrDefault();

settings.Element("SourceFolder").SetValue("filepath");
settings.Element("CopyImages").SetValue(true);

【讨论】:

  • 这个问题是 Descendant 的函数不起作用,它检索到 null(我已经在上面描述过)并且它不想选择我的值。谢谢您或您的帮助,尽管 DaveShaw 的回答确实有效,但我不知道为什么这不起作用而 DaveShaw 的回答确实有效。正如我发布的那样,我对此很陌生,也许我的 xml 构建是错误的。
  • 我已经在我的示例中检查了这一点 - 设置的值为空。
【解决方案3】:

好的,我已经设法解决了这个问题。我不知道为什么,但它奏效了。似乎 Descendants 函数返回 null 作为独立函数,但使用 linq 它可以工作。所以对于我的解决方案,唯一应该做的是:

 var updateData = (from s in configXml.Descendants("Design") 
                   where s.Attribute("name").Value == design.DesignName 
                  select s).First();

起初,在我向您发送我的问题之前,我已经尝试过这个,但我没有 select 部分。此外,当我在大括号中写入 where s.Atribute 部分时,我插入了 design.DesignName 对象而不是属性名称。所以不,它工作正常。感谢您的帮助和一切。直到下一次。大家有一个美好的白天/黑夜:)

【讨论】:

    【解决方案4】:

    因为 DesignConfiguration 是您的根节点,所以 Descendants("DesignConfiguration) 返回 null。通过使用 .Descendants("Design"),您看到的是子节点,而不是自身。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-26
      • 2015-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多