c# – 有没有办法立刻替换整个XML节点?

我需要用指定用户的更新产品列表替换产品列表(UserCart).如果不打电话给每个房产怎么办呢?

<Users>
<UserInfo>
  <Name>ddd</Name>
  <Wallet>0</Wallet>
  <UserCart>
    <Products_>
      <MedicineProduct
        Product_Name="sak"
        Product_ID="0"
        Price="0"
        Quntity="0"
        Image="" />
    </Products_>
  </UserCart>
</UserInfo>

这是我卡住的地方……

public static void Edit(UserInfo user, Products usercart)
{
    XmlDocument doc = new XmlDocument();
    doc.Load(path);
    XmlNode node = doc.SelectSingleNode(string.Format("//UserInfo[./Name/text()='{0}']", user.Name));
}

找到指定的用户.如何用新值替换整个UserCart节点?

最佳答案 您可以尝试使用较新的XDocument API来使用XML及其
XElement.ReplaceWith()方法.

var xml = "<Users><UserInfo><Name>Old Name</Name></UserInfo></Users>";
var document = XDocument.Parse(xml);
var replacedNode = document.Descendants("UserInfo")
                           .SingleOrDefault(x => x.Descendants("Name")
                                                  .Single()
                                                  .Value == "Old Name");

// The code below uses C# 6.0 null propagation feature to handle 
// the case when replacedNode is null (not found in XML).
// In case you use C# 5.x or lower, you can just check it in an IF statement
replacedNode?.ReplaceWith(new XElement("UserInfo", 
                                       new XElement("Name", "New Name")));

Console.WriteLine(document.ToString());

更新(2016年1月14日)

下面是一个快速示例,说明如何编写扩展方法来替换用户的购物车.虽然这绝对是可行的,但我会避免混淆业务逻辑(用户购物车更新)和基础架构/数据层(序列化).我宁愿看到用户对象从XML反序列化,更新,然后序列化.

public static class XmlExtensions
{
    public static XElement ToXElement(this object obj)
    {
        using (var memoryStream = new MemoryStream())
        {
            using (TextWriter streamWriter = new StreamWriter(memoryStream))
            {
                var xmlSerializer = new XmlSerializer(obj.GetType());
                xmlSerializer.Serialize(streamWriter, obj);
                return XElement.Parse(Encoding.ASCII.GetString(memoryStream.ToArray()));
            }
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        var xml = "<Users><UserInfo><Name>Old Name</Name><UserCart></UserCart></UserInfo></Users>";

        var document = XDocument.Parse(xml);

        var userCart = document.Descendants("UserInfo")
            .SingleOrDefault(x => x.Descendants("Name").Single().Value == "Old Name")
            ?.Element("UserCart");

        var newUserCart = new UserCart
        {
            Products = new List<Product>
            {
                new Product { Name = "First" },
                new Product { Name = "Second" }
            }
        };

        userCart?.ReplaceWith(newUserCart.ToXElement());

        Console.WriteLine(document.ToString());
    }
}

public class UserCart
{
    public List<Product> Products { get; set; } 
}

public class Product
{
    public string Name { get; set; }
    public int Quantity { get; set; }
}

正如我在评论中提到的,您还可以使用System.Xml命名空间中的属性(例如XmlElement)来控制序列化.请注意,XmlSerializer有其局限性.例如,它无法将接口开箱即用.

点赞