Jesper Tverskov, August 4, 2008

Add XML with W3C DOM in ASP.NET

In ASP.NET we have two main APIs for editing XML: W3C DOM and LINQ to XML. In this tutorial we look at how to add elements and attributes in W3C DOM. There are many more properties and methods and ways of achieving the same result than shown below. You must look up the proper documentation for all the details.

Editing XML basically consists of the following: adding, deleting or replacing elements and attributes, and updating content of elements and values of attributes. An API for editing also has properties and methods for comments, processing instructions, etc, but in this tutorial we only look at how to add elements and attributes.

1. Add element

I use the following XML document, products.xml, in many of my XML tutorials. How could we add a "test" element and make it a child of the "products" element.

<?xml version="1.0" encoding="utf-8"?>
<products>
  <product id="p1">
    <name>Delta</name>
    <price>800</price>
    <stock>4</stock>
    <country>Denmark</country>
  </product>
  ...
  <product id="p3">
    <name>Alfa</name>
    <price>1200</price>
    <stock>19</stock>
    <country>Germany</country>
  </product>
  ...
</products>

There are basically four ways of adding an element. Take the parent element and use PrependChild() or AppendChild() to add the new child as first or last child. Or take the parent element and a reference child element and use InsertBefore() or InsertAfter() to add the new child before or after the reference child.

In the following we show all four methods, adding the same "test" element four times.

2. W3C DOM

2.1 add-xml-w3cdom.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="add-xml-w3cdom.aspx.cs" Inherits="add_xml_w3cdom" %>

2.2 add-xml-w3cdom.aspx.cs

using System;
using System.Xml;

public partial class add_xml_w3cdom : System.Web.UI.Page
{
  protected void Page_Load(object sender, EventArgs e)
    {
      XmlDocument xmldoc = new XmlDocument();
      xmldoc.Load(Server.MapPath("products.xml"));

      // parent element of the element we want to replace
      XmlNode parentElement = xmldoc.SelectSingleNode("products");

      // reference element
      XmlNode refXmlNode = xmldoc.SelectSingleNode("products/product[@id = 'p3']");

      // new element
      XmlElement newXmlElement = xmldoc.CreateElement("test");

      // content for new element
      XmlText newText = xmldoc.CreateTextNode("abc");
      newXmlElement.AppendChild(newText);

      // a) prepend new element
      parentElement.PrependChild(newXmlElement);

      // b) append new element
      parentElement.AppendChild(newXmlElement);

      // c) insert new element before ref element
      parentElement.InsertBefore(newXmlElement, refXmlNode);

      // d) insert new element after ref element
      parentElement.InsertAfter(newXmlElement, refXmlNod

      xmldoc.Save(Server.MapPath("products.xml"));
      Response.Redirect("products.xml"); // load file in browser
    }
}

The W3C DOM API takes more code than LINQ to XML but the nice thing about W3C DOM is that it is a standard API implemented by most programming languages. We can even read or edit an HTML document more or less the same using the HTML version of W3C DOM.

3. Add attribute

Let us say that we want to add a "test" attribute to the product element already having an "id" attribute with a "p3" value. Adding attributes are known to cause problems for many users. Attributes are not children of their parent element (!): we must choose properties and methods carefully. See: Accessing Attributes in the DOM, at MSDN.

Attributes are easy in one sense: the order of attributes in an element are not important and attribute names in an element must be unique. We simply take the parent element and create the new attribute.

The easiest way is to create an XmlElement object for the parent of the attribute instead of just an XmlNode object. Note that when we create the XmlElement object using "xmldoc.SelectSingleNode", we must do it explicitly adding "(XmlElement)" in front of xmldoc.

XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(Server.MapPath("products.xml"));

// parent element of the attribute
XmlElement parentElement = (XmlElement)xmldoc.SelectSingleNode("products/product[@id = 'p3']");

// new attribute is created
parentElement.SetAttribute("test", "abc");

xmldoc.Save(Server.MapPath("products.xml"));

4. Add XML in a namespace

See: Read XML with W3C DOM for how to use XmlNameSpaceManager.

Updated 2008-08-05