如何在C#中使用Linq to XML更新XML属性

时间:2016-12-31 17:15:57

标签: c# xml linq

我有一组自定义对象,它们有storeid。我还有一个XmlDocument,我从数据库查询数据并在内存中构造。 custome对象中的StoreId属性对应于XML中的“Value”对象。我必须循环遍历我的自定义集合,并将StoreId与XML中的“Value”属性相匹配,并将其“Checked”属性设置为true。如下面的XML所示,所有“Checked”属性值在开始时都设置为false。

<Tree>
<Node Text="Whole ">
  <Node Text="America">
     <Node Text="NewYork">
        <Node Value="28" Checked="false " Text="NY1" />
        <Node Value="29" Checked="false " Text="NY2" />
     </Node>
     <Node Text="Houston">
        <Node Value="13 " Checked="false " Text="H1" />
        <Node Value="14 " Checked="false " Text="H2" />
        <Node Value="16 " Checked="false " Text="H3" />
        <Node Value="19 " Checked="false " Text="H4" />
        <Node Value="26 " Checked="false " Text="H5" />
     </Node>
     <Node Text="GeorgeTown">
        <Node Value="21 " Checked="false " Text="G1" />
        <Node Value="23 " Checked="false " Text="G2" />
        <Node Value="25 " Checked="false " Text="G3" />
     </Node>
  </Node>
  </Node>
  </Tree>

我的代码是:

public class MyObject
 {
    public string StoreId { get; set; }
    public bool HasValue { get; set; }
 }

 Code to update XML:
 XmlDocument baseDocument = ConstructXMLFromDataBase();
 XmlNodeList dataNodes = baseDocument.SelectNodes("//Tree/Node/Node/Node");

 List<MyObject> myCollections = GetMyCollection();

 foreach (var myCollection in myCollections)
 {
    foreach (XmlNode node in dataNodes)
    {
      //code to update
    }               
 }

我相信可以使用Linq to XML轻松完成,而且我对Linq to XML非常新。此外,互联网上提供的大多数样本都是关于更新从光盘加载的XML而不是在内存中构建的。

由于

3 个答案:

答案 0 :(得分:1)

您可以通过添加一个内部循环来完成您的方法更新:

foreach (XmlNode checkedNode in node.ChildNodes)
{
    checkedNode.Attributes["Checked"].Value = "true";
}

如果你想使用Linq,你应该切换到XDocument:

var doc = XDocument.Parse(xml);     //xml is a string, can be returned from a function, 
                                    //built dynamically, etc.

var nodesToUpdate = doc.Descendants("Node")
                       .Where(n => n.Attributes("Checked").FirstOrDefault() != null);

foreach (var node in nodesToUpdate)
{
    //TODO: check update conditions, etc.

    node.Attribute("Checked").Value = "true";
}

答案 1 :(得分:0)

如果要使用LINQ to Xml,则需要更改ConstructXMLFromDataBase方法以返回XDocument对象。

XDocument document = ConstructXMLFromDataBase();

如果您从数据库加载的字符串构造了xml,则可以使用

return XDocument.Parse(validXmlString);

如果您的xml不是有效文档(没有<?xml..标记),那么您可以返回XElement

return XElement.Parse(yourXmlString);

或使用&#34;脏&#34;解决方法并将其转换为XDocument

XmlDocument xmlDocument = ConstructXMLFromDataBase();
XDocument document;
using (var nodeReader = new XmlNodeReader(xmlDocument))
{
    document = XDocument.Load(nodeReader);    
}

然后更新现有节点。此代码适用于document is XDocumentdocument is XElement

这两种情况
var storeIdCollection = GetMyCollection().Select(myObject => myObject.StoreId);
var storeIds = new HashSet<string>(storeIdCollection);

var nodes = document.Descendants.Where(node => node.Attribute("Value") != null);
foreach(var node In nodes)
{
    var storeId = node.Attribute("Value").Value;
    If (storeIds.Contains(storeId))
    {
        node.Attribute("Checked").Value = "true";
    }
}

答案 2 :(得分:0)

我发现Linq2Xml + XPath更易于使用

var id = "19";
var xdoc = XDocument.Load(filename);

xdoc.XPathSelectElement($"//Node[@Value='{id}']").Attribute("Checked").Value = "true";

xdoc.Save(filename);