使用XElement时出现NullReferenceException

时间:2011-08-30 13:33:19

标签: c# xml linq-to-xml xelement

我有一个方法可以编辑xml文件:

    public void EditItem(Item item, string xml)
    {
        Data = XDocument.Load(HttpContext.Current.Server.MapPath("~/App_Data/Items/" + xml + ".xml"));

        XElement node = Data.Root.Elements("item").Where(i => (string)i.Element("ID") == item.ID).FirstOrDefault();

        node.SetElementValue("ID", item.ID);
        node.SetElementValue("Name", item.Name);
        node.SetElementValue("Type", item.Type);
        node.SetElementValue("Kr", item.Kr);
        node.SetElementValue("Euro", item.Euro);

        Data.Save(HttpContext.Current.Server.MapPath("~/App_Data/Tables/" + xml + ".xml"));
    }

我通过控制器中的try / catch获得此验证错误:“对象引用未设置为对象的实例。”通过一些调试,我发现“node”为null,即使“Data”包含来自xml的所有正确数据,并且model.ID是正确的。

奇怪的是,我让它在另一个repo中工作,其中xml不是动态的,并且XDocument obj在构造函数中加载。

任何想法是什么原因造成的?或者也许是关于变通方法的一些想法。

更新。 Xml片段:

<?xml version="1.0" encoding="utf-8"?>
    <catagory id="0">
      <module>
        <item>
          <ID>101</ID>
          <Name>ClassicoTable(35x100x100)</Name>
          <Type>Model</Type>
          <Kr>0</Kr>
          <Euro>0</Euro>
          <DataType>ClassicoTableA</DataType>
        </item>
        <item>
          <ID>100</ID>
          <Name>ClassicoTable(102x100x140)</Name>
          <Type>Model</Type>
          <Kr>0</Kr>
          <Euro>0</Euro>
          <DataType>ClassicoTableB</DataType>
        </item> 



       ......

      </module>
    </catagory id="0">

2 个答案:

答案 0 :(得分:1)

这一行:

XElement node = Data.Root.Elements("item").Where(i => (string)i.Element("ID") == table.ID).FirstOrDefault();

是这个(不确定table.ID来自哪里):

XElement node = Data.Root.Elements("item").Where(i => (string)i.Element("ID") == item.ID).FirstOrDefault();

我还会检查节点是否为空:

public void EditItem(Item item, string xml)
{
    Data = XDocument.Load(HttpContext.Current.Server.MapPath("~/App_Data/Items/" + xml + ".xml"));

    XElement node = Data.Root.Elements("item").Where(i => (string)i.Element("ID") == item.ID).FirstOrDefault();

    if (node != null)
    {
        node.SetElementValue("ID", item.ID);
        node.SetElementValue("Name", item.Name);
        node.SetElementValue("Type", item.Type);
        node.SetElementValue("Kr", item.Kr);
        node.SetElementValue("Euro", item.Euro);

        Data.Save(HttpContext.Current.Server.MapPath("~/App_Data/Tables/" + xml + ".xml"));
    }
}

答案 1 :(得分:0)

好的找到了解决方案。我开始想知道为什么@Kim想从我的xml中获取一个片段。所以它让我觉得Data.Root.Element()可能不是正确的方法。所以我尝试使用Descendants(),这实际上是有效的。为什么?我没有线索。这是为什么:

在另一个回购中,我在回购的构造函数中有XDocument.load()。我认为这样会很好,因为那样我就不必在所有CRUD方法中重复相同的代码。但是,因为我想要xml动态,并且构造函数不接受参数,我认为这样(原始问题)会很好。这里是“静态”仓库的代码:

//Constructor
public CubeRepository()
{
    allCubes = new List<Cube>();

    CubeData = XDocument.Load(HttpContext.Current.Server.MapPath("~/App_Data/Cubes/Cubep10p11.xml"));
    var cubes = from cube in CubeData.Descendants("item")
                select new Cube(cube.Element("ID").Value, 
                    cube.Element("Name").Value, 
                    cube.Element("Type").Value,
                    (int)cube.Element("Kr"),
                    (int)cube.Element("Euro"));

    allCubes.AddRange(cubes.ToList<Cube>());
}

在我的回购编辑方法中:

public void EditCube(Cube cube)
{
    XElement node = CubeData.Root.Elements("item").Where(i => (string)i.Element("ID") == cube.ID).FirstOrDefault();
    node.SetElementValue("ID", cube.ID);
    node.SetElementValue("Name", cube.Name);
    node.SetElementValue("Type", cube.Name);
    node.SetElementValue("Kr", cube.Kr);
    node.SetElementValue("Euro", cube.Euro);

    CubeData.Save(HttpContext.Current.Server.MapPath("~/App_Data/Cubes/Cubep10p11.xml"));
}

即使我使用CubeData.Root.Elements("item"),这就像我的魅力一样。注意:ElementsDescendants。 xml文件的结构是相同的。