【问题标题】:how to edit particular item in linq to xml如何将linq中的特定项目编辑为xml
【发布时间】:2016-10-03 06:51:46
【问题描述】:

我必须创建一个 xml 文档并通过 LINQ to XML 概念执行以下项目。

  1. 添加新资产,
  2. 编辑资产,
  3. 移除资产。

我正在通过记事本创建一个 xml 文档并通过“asset.xml”保存该文件,然后将该文件复制到调试文件夹中

我的xml文档格式是

<?xml version="1.0" encoding="utf-8"?>
<Assets>
  <assetId>1
       <assetName>lenova</assetName>
       <model>12kj320</model>
       <price>22000</price>
       <quantity>12</quantity>
   </assetId>
</Assets>

我的代码是

class program
{

public static void AddSingleAsset()
{
    static List<Asset> Assets = new List<Asset>();

    int assetId;
    string assetName;
    string model;
    double price;
    int quantity;
    assetId = Assets.Count + 1;
    Console.WriteLine("Asset id :{0}", assetId);
    Console.WriteLine("Enter the asset name");
    assetName = Console.ReadLine();
    Console.WriteLine("Enter the asset model");
    model = Console.ReadLine();
    Console.WriteLine("Enter the price of asset");
    price = int.Parse(Console.ReadLine());
    Console.WriteLine("Enter the quantity of asset");
    quantity = int.Parse(Console.ReadLine());
    Assets.Add(new Asset() { assetId = assetId, assetName = assetName, modelNo = model, price = price, quantity = quantity });
    string path = "linqtoxml1.xml";
    XDocument doc = XDocument.Load(path);
    doc.Elements("Assets").First().AddFirst(new XElement("assetId", assetId, new XElement("assetName", assetName), new XElement("model", model), new XElement("price", price), new XElement("quantity", quantity)));
    doc.Save(path);

}
public static void EditAssetInformation()
{
    Console.WriteLine("select the option to edit");
    Console.WriteLine("1.To change Asset Name\n2.To change Model NO\n3.To change price\n4.To change Quantity");
    int option = int.Parse(Console.ReadLine());
    switch (option)
    {
        case 1:
            string newname;
            Console.WriteLine("Enter the ID number to change the information");
            int id = int.Parse(Console.ReadLine());
            Console.WriteLine("Enter the Asset new name");
            newname = Console.ReadLine();
            ModifyName(newname, id);    
            break;

        case 2:
            string newModelNo;
            Console.WriteLine("Enter the ID number to change the information");
            int id1 = int.Parse(Console.ReadLine());
            Console.WriteLine("Enter the Asset new model No");
            newModelNo = Console.ReadLine();
            ModifyModelNo(newModelNo, id1);
            break;

        case 3:
            double newPrice;
            Console.WriteLine("Enter the ID number to change the information");
            int id2 = int.Parse(Console.ReadLine());
            Console.WriteLine("Enter the Asset new price");
            newPrice = int.Parse(Console.ReadLine());
            ModifyPrice(newPrice, id2);
            break;

        case 4:
            int newQuantity;
            Console.WriteLine("Enter the ID number to change the information");
            int id3 = int.Parse(Console.ReadLine());
            Console.WriteLine("Enter the Asset new price");
            newQuantity = int.Parse(Console.ReadLine());
            Modifyquantity(newQuantity, id3);
            break;

        }
    }
    static void ModifyName(string newname, int id)
    {
        var doc = XElement.Load(path);
        var namechange = doc.Element("Assets").Elements("assetId").Where(c => c.Element("assetId").Value == Convert.ToString(id)).Single();
        namechange.Element("assetName").Value = newname;
        doc.Save(path);
    }
    static void ModifyModelNo(string newModelNo, int id1)
    {
        string path = "linqtoxml1.xml";
        XDocument doc = XDocument.Load(path);
        XElement modelchange = doc.Descendants("AssetId").Where(c => c.Attribute("AssetId").Value.Equals(id1.ToString())).FirstOrDefault();
        modelchange.Element("model").Value = newModelNo;
        doc.Save(path);
    }
    static void ModifyPrice(double newPrice, int id2)
    {
        string path = "linqtoxml1.xml";
        XDocument doc = XDocument.Load(path);
        XElement pricechange = doc.Descendants("AssetId").Where(c => c.Attribute("AssetId").Value.Equals(id2.ToString())).FirstOrDefault();
        pricechange.Element("price").Value = newPrice.ToString();
        doc.Save(path);
    }
    static void Modifyquantity(int newQuantity, int id3)
    {
        string path = "linqtoxml1.xml";
        XDocument doc = XDocument.Load(path);
        XElement quantitychange = doc.Descendants("AssetId").Where(c => c.Attribute("AssetId").Value.Equals(id3.ToString())).FirstOrDefault();
        quantitychange.Element("quantity").Value = newQuantity.ToString();
        doc.Save(path);
    }
    public static void DeleteAssetInformation()
    {
        string path = "linqtoxml1.xml";
        Console.WriteLine("Enter the ID to delete information");
        int id = int.Parse(Console.ReadLine());
        XDocument doc = XDocument.Load(path);
        XElement cStudent = doc.Descendants("AssetId").Where(c => c.Attribute("ID").Value.Equals(id.ToString())).FirstOrDefault();
        cStudent.Remove();
        doc.Save(path);
    }
}
public class Asset
{
    public int assetId
    { get; set; }
    public string assetName
    { get; set; }
    public string modelNo
    { get; set; }
    public double price
    { get; set; }
    public int quantity
    { get; set; }
}

我的问题是

我需要自动生成资产 ID。我的代码在我关闭此控制台并再次运行时连续添加元素时有效,然后资产 ID 将从 1 重新开始。

当我尝试编辑或删除上一条记录时,也意味着将显示错误:

SYSTEM.NULL 引用异常

谁能解释一下我在这个程序中做错了什么,并建议我纠正这个问题的简单方法。基本上我来自非 IT 领域,我是一名电气工程师,所以请稍微深入解释一下。

【问题讨论】:

  • From : Where(c => c.Attribute("ID").Value.Equals(id.ToString()) To : Where(c => (int)c == id)
  • 你最好使用XmlSerializer 来做这个。完成后对Asset 列表/对象进行更改并序列化。您的 LINQ to XML 代码错综复杂(XML 区分大小写)并且混淆了元素和属性。

标签: c# xml linq


【解决方案1】:

嗯,我看到你的代码发生了一些事情

XML 文件

你的 xml 看起来像这样

<?xml version="1.0" encoding="utf-8"?>
<Assets>
  <assetId>1
       <assetName>lenova</assetName>
       <model>12kj320</model>
       <price>22000</price>
       <quantity>12</quantity>
   </assetId>
</Assets>

节点无效 - 你应该在值之后结束这个节点。 &lt;assetId&gt; 节点是有效的,但是稍微改变一下这个结构会更好。如果您有名为&lt;Assets&gt; 的节点,最好将每个资产封装在他自己的节点中,称为&lt;asset&gt;

<?xml version="1.0" encoding="utf-8"?>
<Assets>
   <asset>
      <assetId>1</assetId>
      <assetName>lenova</assetName>
      <model>12kj320</model>
      <price>22000</price>
      <quantity>12</quantity>
   </asset>
</Assets>

在此更改后,您将能够轻松找到所有资产

var assets = root.Elements("asset");

如果您想添加新资产并获得正确的新 id 值,您可以这样做

var assets = root.Elements("asset").OrderByDescending(asset => asset.Element("assetId").Value);

现在,id 值最高的资产在顶部,所以,要计算新的 id,你应该这样做

var newestAsset = root.Elements("asset").OrderByDescending(asset => asset.Element("assetId").Value).FirstOrDefault();
int newId = int.Parse(newestAsset.Element("assetId").Value) + 1;

所以添加新资产看起来像这样

XElement root = XElement.Load(path);
XElement newAsset = new XElement("asset", new XElement("assetId", newId)/*, other asset properties */);
root.Add(newAsset);
root.Save(path);

空引用异常

这个异常意味着,你试图使用某个变量,但是这个变量是空的,所以它没有任何值。从第一次看你的代码我可以看到,在某些地方你试图加载 xml 元素,使用路径变量,但它没有被初始化。例如在ModifyName 方法中。

另一种可能是,这条线有问题

var namechange = doc.Element("Assets").Elements("assetId").Where(c => c.Element("assetId").Value == Convert.ToString(1)).Single();

还有这个

XElement modelchange = doc.Descendants("AssetId").Where(c => c.Attribute("AssetId").Value.Equals(1.ToString())).FirstOrDefault();

我猜,这两条线中的某处都为空,但无论哪种方式,您都在尝试处理此元素。在这种情况下,您应该真正使用调试器并查看此异常来自何处。有了这些信息,您将知道应该更改哪些行以使该程序正常运行。

如果您想从控制台窗口查找用户提供的 id 资产,代码应如下所示

var asset = root.Elements("asset").Where(asset => asset.Element("assetId").Value == id.ToString()); 

首先,将您的 xml 结构更改为我建议的结构,而不是使用此答案中的 sn-ps 重写我指出的这些行,您应该一切顺利!

【讨论】:

  • '节点无效' - 这不是真的。它可能不是理想的表示形式(您的建议更好),但它是完全有效的 XML。
  • 在这种情况下,我将编辑我的答案 - 感谢您指出这一点! 编辑: 其实我不知道我在想什么,因为像&lt;span&gt;Something &lt;strong&gt;very&lt;/strong&gt; important&lt;/span&gt; 这样的 HTML 确实是一个完全有效的语法......
  • @Arunkumar 如果我的回答对您有帮助,请继续接受它
  • @PawełHemperek 我还有疑问?我想打印没有 xml 格式的值,我该怎么做?
  • 对不起 - “我想打印没有 xml 格式的值”是什么意思?你在说什么价值?您不想将数据保存到 xml 文件,还是在控制台中显示它并且它是 xml 格式的?
猜你喜欢
  • 2022-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-02
相关资源
最近更新 更多