我有一个具有以下结构的XML文件:
<inventory>
<product>
<recordNumber>1</recordNumber>
<name>Dustbin</name>
<stock>190</stock>
<price>33</price>
</product>
<product>
<recordNumber>2</recordNumber>
<name>Broom</name>
<stock>200</stock>
<price>76</price>
</product>
</inventory>
我有一个程序,它接受这些值并创建一个列表&#39;项目&#39;称为&#39; stockArray&#39;的对象。每个项目都有一个int-Id(来自recordNumber
)和一个int-count(来自stock
)。
该程序更新&#34; stock&#34;相应的值和我想要做的是然后更新XML文件以获得新的&#39; stock&#39;值。
我是C#和XML的新手,所以这就是我一直走下去的路径:
XDocument doc = XDocument.Load(xml);
var list = doc.Element("inventory").Elements("product");
foreach (var node in list)
{
foreach (Item item in stockArray)
{
if (node.Element("recordNumber").Value == Convert.ToString(item.Id))
node.SetElementValue("count", Convert.ToString(item.count));
}
}
但到目前为止,这似乎已经过时了。我可以找到很多关于向XML添加新节点的信息,但是遍历stockArray
项列表并更新XML似乎是一个不同的过程。
非常感谢任何建议。
答案 0 :(得分:2)
您的XML没有<count>
元素。如果您要更新<stock>
元素值,SetElementValue()
的第一个参数应为"stock"
:
if (node.Element("recordNumber").Value == Convert.ToString(item.Id))
node.SetElementValue("stock", Convert.ToString(item.count));
使用LINQ连接创建匿名类型的一种可能方式,将<product>
元素与stockArray
中的相应项绑对:
var list = from product in doc.Element("inventory").Elements("product")
join item in stockArray on (int)product.Element("recordNumber") equals item.id
select new {product = product, item = item};
foreach (var joinedProduct in list)
{
joinedProduct.product.SetElementValue("stock", joinedProduct.item.count);
}
答案 1 :(得分:0)
试试这个,但你会想要对空值进行一些错误处理。
var doc = XDocument.Load(xml);
var list = doc.Element("inventory").Elements("product");
foreach (var item in stockArray)
{
var node = list.FirstOrDefault(p => p.Element("recordNumber").Value == item.ToString());
node.Element("stock").Value = item.Count.ToString();
}
编辑:修复代码!
答案 2 :(得分:0)
您正在修改count
元素而不是stock
元素。
并提高性能(这里的复杂性是O(n ^ 2))。您可以从stockArray
创建字典。
创建字典的复杂度为O(n)。 在字典中获取值的复杂度为O(1)。
因此,使用字典的程序的复杂性是O(n)。
我还建议您使用explicit cast将XElement
的值转换为int
。
XDocument doc = XDocument.Load(xml);
var list = doc.Element("inventory").Elements("product");
var stockDictionary = stockArray.ToDictionary(item => item.Id, item => item.Count);
foreach (var node in list)
{
int newCount;
if (if(stockDictionary.TryGetValue((int)node.Element("recordNumber"), out newCount)
node.SetElementValue("stock", newCount);
}
答案 3 :(得分:0)
您可以使用XmlSerializer执行此操作。唯一的事情是你必须把你的xml结构写成类。请参阅代码示例。
class Program
{
static void Main(string[] args)
{
// Create a new file stream for reading the XML file
FileStream ReadFileStream = new FileStream(@"C:\files\data.xml", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
// Load the object saved above by using the Deserialize function
Inventory LoadedObj = (Inventory)SerializerObj.Deserialize(ReadFileStream);
// Cleanup
ReadFileStream.Close();
foreach (var node in LoadedObj.Products)
{
// node.Stock = 0;
//Do what ever changes to stock
}
XmlSerializer SerializerObj = new XmlSerializer(typeof(Inventory));
//// Create a new file stream to write the serialized object to a file
TextWriter WriteFileStream = new StreamWriter(@"C:\files\data.xml");
SerializerObj.Serialize(WriteFileStream, TestObj);
//// Cleanup
WriteFileStream.Close();
}
}
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlRoot("inventory")]
public class Inventory
{
[System.Xml.Serialization.XmlElement("product")]
public List<Product> Products { get; set; }
}
[System.SerializableAttribute()]
public class Product
{
[System.Xml.Serialization.XmlElementAttribute("recordNumber")]
public string RecordNumber { get; set; }
[System.Xml.Serialization.XmlElementAttribute("name")]
public string Name { get; set; }
[System.Xml.Serialization.XmlElementAttribute("stock")]
public int Stock { get; set; }
[System.Xml.Serialization.XmlElementAttribute("price")]
public int Price { get; set; }
}