我需要用指定用户的更新产品列表替换产品列表(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节点?
答案 0 :(得分:2)
您可以尝试使用较新的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
有其局限性。例如,它无法将接口开箱即用。
答案 1 :(得分:0)
这取决于您想要替换它的内容。如果你只想在那里设置一些文字,那很简单:
XmlNode cart = doc.SelectSingleNode(string.Format("//UserInfo[./Name/text()='{0}']/UserCart", "ddd"));
cart.InnerText = "Replaced!";
注意我更改了您的选择器,因此您将获得实际的购物车节点而不是其父节点。
如果要将其替换为新的XML节点,则必须创建它们,将它们添加到文档中,然后附加它们:
XmlNode cart = doc.SelectSingleNode(string.Format("//UserInfo[./Name/text()='{0}']/UserCart", "ddd"));
// clear out nodes
cart.RemoveAll();
cart.AppendChild(doc.CreateNode(XmlNodeType.Element, "test", ""));
尽管如此,通常最好使用较新的XDocument
API,它可能看起来像......
XDocument doc = XDocument.Parse(xml);
//doc.LoadXml(xml);
XElement cart = doc.Root.Descendants("UserCart").Where(x => (string)x.Parent.Element("Name") == "ddd").FirstOrDefault();
if (cart != null)
cart.ReplaceNodes(new XElement("test")); // or you can do cart.Value = "text" you're not adding new elements.