Search code examples
c#xmllinqxelement

XElement.Element returning null for newly created element


I am using XElement to create an XMLDocument which is used in a hierarchical WPF treeview. If I create a new element with :

    x_element = new XElement("node",
    new XElement("tree_id", strData[0]),
    new XElement("sys_id", dpl.DepSysId),
    new XElement("part_id", strData[8]),
    new XElement("make", strData[6]),
    new XElement("model", strData[5]),
    new XElement("level", strData[2]));

I then need to add attributes to "node" so I tried:

   XElement temp_el = x_element.Element("node"); // This is returning null
   temp_el.SetAttributeValue("title", strData[7] + " " + strData[6] + " " + strData[5]);
   temp_el.SetAttributeValue("canEdit", "False");
   temp_el.SetAttributeValue("status", nStatus.ToString());
   temp_el.SetAttributeValue("qty", strData[13]);
   temp_el.SetAttributeValue("part", strData[8]);

In the above code temp_el is null, but I can see in the debugger that x_element contains the following :

<node>
  <tree_id>82</tree_id>
  <sys_id>82</sys_id>
  <part_id>169</part_id>
  <make>ST Panel</make>
  <model>Logical Pure 16 tube Collector</model>
  <level>0</level>
</node>

To work around this I have used the following:

   foreach (XElement temp_el in x_element.DescendantsAndSelf())
   {
       if (temp_el.Name == "node")
       {
           temp_el.SetAttributeValue("title", strData[7] + " " + strData[6] + " " + strData[5]);
           temp_el.SetAttributeValue("canEdit", "False");
           temp_el.SetAttributeValue("status", nStatus.ToString());
           temp_el.SetAttributeValue("qty", strData[13]);
           temp_el.SetAttributeValue("part", strData[8]);
           break;
       }
   }

Whilst the above works I am just curious as to why I am getting null returned. Is my workaround the best way of doing this?

Regards.


Solution

  • You defined your XElement like this:

    x_element = new XElement("node", /* child nodes */);
    

    Where "node" is the name of the XElement you are creating, and the following parameters are its children.

    By using x_element.Node("node"), you are trying to get the child node named "node", and there isn't such a child node.
    x_element itself is the node named "node".
    DescendantsAndSelf worked because it includes x_element (hence "AndSelf"), but you don't need this either because you already have the node.

    So you can change your second code snippet to this:

    x_element.SetAttributeValue("title", strData[7] + " " + strData[6] + " " + strData[5]);
    x_element.SetAttributeValue("canEdit", "False");
    // etc.
    

    (BTW, you can also add the Attributes in the constructor)