Create and Add nodes in .Net C# with XmlDocument

Posted by OmegaMan at June 11, 2007

Category: How To

Tags: ,

The tribal knowledge in dealing with XmlDocument in C# is that it takes the reference to a tree and its branches too literally. When pruning or adding to the tree, one must always take from the branch (node) from which it comes to do any operation.  Here are a few examples to work with the XmlDocument

Add Node With Attributes

string xml = @"<?xml version='1.0' encoding='utf-8'?>
   <menu>
    <sub name='A' value='p1.aspx'/>
    <sub name='B' value='p2.aspx'/>
    <sub name='C' value='p3.aspx'/>
   </menu>";'

XmlDocument originalXml = new XmlDocument();
originalXml.LoadXml(xml);

XmlNode menu = originalXml.SelectSingleNode("menu");

XmlNode newSub = originalXml.CreateNode(XmlNodeType.Element, "sub", null);

XmlAttribute xa = originalXml.CreateAttribute("Name");
xa.Value = "D";

XmlAttribute xb = originalXml.CreateAttribute("value");
xb.Value = "p4.aspx";

newSub.Attributes.Append(xa);
newSub.Attributes.Append(xb);

menu.AppendChild(newSub);

Console.WriteLine(originalXml.OuterXml.ToString());

The above code we had a static set of Xml, and added a node with two attributes. Here is the output (pretty printed after the fact and not by the code)

<?xml version="1.0" encoding="utf-8"?>
    <menu>
        <sub name="A" value="p1.aspx" />
        <sub name="B" value="p2.aspx" />
        <sub name="C" value="p3.aspx" />
        <sub Name="D" value="p4.aspx" />
     </menu>

Remove Node

Using the above snippet to remove the “B” node we will search for it then remove it

XmlNode bNode = originalXml.SelectSingleNode("descendant::sub[@name='B']");
if (bNode != null)
    menu.RemoveChild(bNode);
Console.WriteLine(originalXml.OuterXml.ToString());

Which produces this Output

<?xml version="1.0" encoding="utf-8"?>
    <menu>
        <sub name="A" value="p1.aspx" />
        <sub name="C" value="p3.aspx" />
        <sub Name="D" value="p4.aspx" />
    </menu>

Replace Xml Snippet

In this example we will simulate a user making a changes to an xml node say within an editor. All we know is that it has been changed, but we don’t know what. It could be either additions or subtractions of attributes and nodes; regardless it needs to replace an original item.

string xmlInitial =
@"<?xml version='1.0'?>
 <Rules>
  <OpenBalances function='ReOrderFifo'>
   <column name='SecurityID' used='True'/>
   <column name='COL2' used='False'>#@#</column>
   <column name='COL3' used='False'>#@#</column>
  </OpenBalances>
 <ClosedBalances/>
 </Rules>";

string xmlUser =
@"<OpenBalances function='ReOrderFifo' iAmNew='true'>
  <column name='SecurityID' used='True'/>
  <column name='COL3' used='True'>New Item</column>
  <column name='COL5' used='True'>Other Item</column>
 </OpenBalances>";

XmlDocument originalXml = new XmlDocument();
string targetNode = "descendant::*[name(.) ='OpenBalances']";

originalXml.LoadXml( xmlInitial );

// Simulate the selection of the subnode
// for the user to edit in the first nodes
// Rules.
XmlNode editNode = originalXml.SelectSingleNode(targetNode);

// Get a fragment and slide the changed data into it.
XmlDocumentFragment fragment = originalXml.CreateDocumentFragment();
fragment.InnerXml = xmlUser;

// Replace the contents of the editNode with the user fragment.
editNode.ParentNode.ReplaceChild(fragment, editNode);

Console.WriteLine(originalXml.OuterXml);

Here is the resulting output

<?xml version="1.0"?>
 <Rules>
  <OpenBalances function="ReOrderFifo" iAmNew="true">
   <column name="SecurityID" used="True" />
   <column name="COL3" used="True">New Item</column>
   <column name="COL5" used="True">Other Item</column>
  </OpenBalances>
 <ClosedBalances />
 </Rules>
Share

11 Comments

  1. vinh says

    thanks for your article.

    Reply
  2. ammu says

    how to add xmlnodes in loop?

    Reply
  3. campingmap says

    in what loop do you mean? I think the code in this example shows how to add a node, should not be any problem to add more than one

    Reply
  4. omegaman says

    If one is adding nodes in a loop, I believe the standard way of creating Xml is what the person was requesting; to which the blog doesn’t show. BUt this is a specific case which could be extrapolated to a loop though.

    Reply
  5. Girish says

    I have a xml like this

    for this XDocument I want to add one child XElement() under

    I want to write a generic method for this.

    I can do the above like this

    XDocument xdoc=new XDocument()

    XElement xelem=new XElement(“Leaf1, new XAttribute(“name”,”ADO.NET”));

    xdoc.Root.Element(“Parent”).ElementAt(1).Element(“Child”).ElementAt(0).Element(“Leaf”).ElementAt(1).Add(xelem);

    But I dont want to do like this.

    I want something like

    xdoc.Root.Element.Add(xelem);

    Is there anyway to do like this. Cause I will not be knowing the Level of ChildElements.

    Thanks in advance

    Reply
    • OmegaMan says

      I am not seeing what your xElem is like. Could you post this question with xml snippets to MSDN’s Visual C# Language forum and give a link back here. Thanks

      Reply
  6. Abdul says

    I must say the way you presented this solution is excellent…… 🙂

    Thank You.

    Abdul.

    Reply
  7. BobT says

    VERY grateful for this!!

    Reply
  8. pham linh sơn says

    thanks a lot. it realy helpful.

    Reply
  9. Markus says

    Thanks much, code still comes in handy.

    Reply
  10. T1tu5 says

    It’s good work!

    Loop:
    XmlDocument originalXml = new XmlDocument();
    originalXml.LoadXml(xml);
    XmlNode menu = originalXml.SelectSingleNode(“menu”);

    for (int i = 0; i < 100; i++)
    {
    XmlNode newSub = originalXml.CreateNode(XmlNodeType.Element, "sub", null);
    XmlAttribute xa = originalXml.CreateAttribute("Name");
    xa.Value = i.ToString();
    XmlAttribute xb = originalXml.CreateAttribute("value");
    xb.Value = "p" + i.ToString() + ".aspx";
    newSub.Attributes.Append(xa);
    newSub.Attributes.Append(xb);
    menu.AppendChild(newSub);
    }
    originalXml.Save("test.xml");

    Reply

Leave a comment

(required)
(required) (will not be published)

This site uses Akismet to reduce spam. Learn how your comment data is processed.